<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 6.1.0">


  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"liukairui.me","root":"/","images":"/images","scheme":"Muse","darkmode":false,"version":"8.10.1","exturl":false,"sidebar":{"position":"left","display":"hide","padding":18,"offset":12},"copycode":true,"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":true,"comments":{"style":"tabs","active":"valine","storage":true,"lazyload":false,"nav":null,"activeClass":"valine"},"stickytabs":false,"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"prism":false,"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="参加了字节跳动前端训练营,开个文章记录下新学到的东西">
<meta property="og:type" content="article">
<meta property="og:title" content="2022寒假字节跳动前端训练营笔记">
<meta property="og:url" content="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/">
<meta property="og:site_name" content="LiuKairui Website">
<meta property="og:description" content="参加了字节跳动前端训练营,开个文章记录下新学到的东西">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/frontend-map.png">
<meta property="og:image" content="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/NodeStruct.jpg">
<meta property="og:image" content="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/webpack5-mindmap.png">
<meta property="og:image" content="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/MSE-follow.jpg">
<meta property="article:published_time" content="2022-01-15T19:12:20.000Z">
<meta property="article:modified_time" content="2022-01-28T12:12:12.211Z">
<meta property="article:author" content="Liu Kairui">
<meta property="article:tag" content="前端">
<meta property="article:tag" content="笔记">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/frontend-map.png">


<link rel="canonical" href="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/","path":"article/2022寒假字节跳动前端训练营笔记/","title":"2022寒假字节跳动前端训练营笔记"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>2022寒假字节跳动前端训练营笔记 | LiuKairui Website</title>
  

  <script src="/js/third-party/analytics/baidu-analytics.js"></script>
  <script async src="https://hm.baidu.com/hm.js?ea07bceb8f5fa721da2ebf01833faa32"></script>



<div class="nindexBK">
<div class="nindexBKC"></div>
<div class="nindex">
  <h1>Hey👋</h1>
  <p style="font-weight: 500; font-size: 2.2em">欢迎访问Liu Kairui的个人站.</p>
  <p>
      我是一个来自重庆的在校大学生, 偏爱于前端技术<!--与OS设计-->, 偶尔使用 JS / Go 进行轻量项目开发, 欢迎访问我的
      <a href="https://github.com/KairuiLiu" target="_blank"><i class="fab fa-github-alt"></i> GitHub</a> .
  </p>
  <p>
      这个网站主要用来存储学习 / 瞎搞的笔记, 同时提供了邮件、图床等服务. 对于一些自认为有趣的<a href="javascript:;" id="myProj">项目</a>, 我也会将项目介绍, 文档, 甚至是设计指南发布在这里.
  </p>
  <ul>
    <li><p><a href="/artrank/" target="_blank">ArtRank</a>: 基于Node.JS的PageRank文献管理推荐系统</p></li>
    <li><p><a href="/gooj/" target="_blank">GoOJ</a>: 基于Golang的高校在线评测系统</p></li>
    <li><p><a href="/projects/" target="_blank">更多 <i class="fas fa-angle-right"></i></a></p></li>

  </ul>
  <p>
      可以在这些平台找到我: 
      <a href="https://www.zhihu.com/people/liu-kai-rui-18" target="_blank">知乎</a>,
      <a href="https://space.bilibili.com/33238144" target="_blank">bilibili</a>
      和
      <a href="https://www.coolapk.com/u/805314?from=qr" target="_blank">酷安</a>.
  </p>

  <p>
      下滑即可进入博客 <i class="fas fa-arrow-down"></i>
  </p>
</div>
</div>  

 
<script>
  var OriginTitile = document.title;
  var titleTime;
  document.addEventListener("visibilitychange", function() {
    if (document.hidden) {
      document.title = "谢谢离开 | " + OriginTitile;
      clearTimeout(titleTime);
    } else {
      document.title = "欢迎归来 | " + OriginTitile;
      titleTime = setTimeout(function() {
        document.title = OriginTitile;
      }, 2000);
    }
  });
</script>


<script>
  function checkIndex(){
    let nindexItems = [[".nindexBK","display","block","none"],[".headband","display","none","block"],["div.toggle.sidebar-toggle","visibility","hidden","visible"]]; // ,["button.darkmode-toggle","visibility","hidden","visible"]];
    let isIndex = new RegExp("^(\/){0,1}(index){0,1}(\.html){0,1}(/)*$").test(location.pathname);
    let backCanvas = document.querySelector(".nindexBK");
    nindexItems.dispShift = function (stat){this.forEach((e) => {try{document.querySelector(e[0]).style[e[1]]=e[2+stat];}catch{}})}
    if(isIndex){
      nindexItems.dispShift(0);
      window.onscroll=function(){
        if(document.documentElement.scrollTop>backCanvas.offsetHeight*1.05){
          nindexItems.dispShift(1);window.onscroll=null;
        }
      }
      document.querySelector("#myProj").onclick=()=>{
        let projlist = document.querySelector(".nindex>ul");
        projlist.className.indexOf("ulactive")==-1?projlist.classList.add("ulactive"):projlist.classList.remove("ulactive")
      }
    }else nindexItems.dispShift(1);
  }
  checkIndex();
</script>

<!--<script src="https://sdk.jinrishici.com/v2/browser/jinrishici.js" charset="utf-8"></script>-->

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<link rel="alternate" href="/atom.xml" title="LiuKairui Website" type="application/atom+xml">
<style>.darkmode--activated{--body-bg-color:#282828;--content-bg-color:#333;--card-bg-color:#555;--text-color:#ccc;--blockquote-color:#bbb;--link-color:#ccc;--link-hover-color:#eee;--brand-color:#ddd;--brand-hover-color:#ddd;--table-row-odd-bg-color:#282828;--table-row-hover-bg-color:#363636;--menu-item-bg-color:#555;--btn-default-bg:#222;--btn-default-color:#ccc;--btn-default-border-color:#555;--btn-default-hover-bg:#666;--btn-default-hover-color:#ccc;--btn-default-hover-border-color:#666;--highlight-background:#282b2e;--highlight-foreground:#a9b7c6;--highlight-gutter-background:#34393d;--highlight-gutter-foreground:#9ca9b6}.darkmode--activated img{opacity:.75}.darkmode--activated img:hover{opacity:.9}.darkmode--activated code{color:#69dbdc;background:0 0}button.darkmode-toggle{z-index:9999}.darkmode-ignore,img{display:flex!important}</style></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">LiuKairui Website</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">要有信仰</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu">
        <li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>首页</a></li>
        <li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类</a></li>
        <li class="menu-item menu-item-tags"><a href="/tags/" rel="section"><i class="fas fa-hashtag fa-fw"></i>标签</a></li>
        <li class="menu-item menu-item-收藏夹"><a href="/favorites/" rel="section"><i class="fab fa-gratipay fa-fw"></i>收藏夹</a></li>
        <li class="menu-item menu-item-留言板"><a href="/messageBoard/" rel="section"><i class="fab fa-facebook-messenger fa-fw"></i>留言板</a></li>
        <li class="menu-item menu-item-项目"><a href="/projects/" rel="section"><i class="fa fa-satellite fa-fw"></i>项目</a></li>
        <li class="menu-item menu-item-图床"><a href="http://img.liukairui.me/" rel="noopener" target="_blank"><i class="fa fa-bed fa-fw"></i>图床</a></li>
        <li class="menu-item menu-item-云ide"><a href="http://vsc.liukairui.me/" rel="noopener" target="_blank"><i class="fas fa-code fa-fw"></i>云IDE</a></li>
        <li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于</a></li>
        <li class="menu-item menu-item-邮箱"><a href="http://mail.liukairui.me/mail" rel="noopener" target="_blank"><i class="fas fa-envelope-open-text fa-fw"></i>邮箱</a></li>
        <li class="menu-item menu-item-rss"><a href="/atom.xml" rel="section"><i class="fa fa-rss fa-fw"></i>RSS</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</div>
        
  
  <div class="toggle sidebar-toggle" role="button">
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
    <span class="toggle-line"></span>
  </div>

  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-3"><a class="nav-link" href="#day0-%E5%AD%97%E8%8A%82%E7%AC%94%E8%AF%95"><span class="nav-number">1.</span> <span class="nav-text">Day0 字节笔试</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day1-1-%E5%89%8D%E7%AB%AF%E4%B8%8Ehtml---%E9%9F%A9%E5%B9%BF%E5%86%9B"><span class="nav-number">2.</span> <span class="nav-text">Day1-1 前端与HTML - 韩广军</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#html%E6%A0%87%E7%AD%BE%E5%A4%8D%E4%B9%A0"><span class="nav-number">2.1.</span> <span class="nav-text">HTML标签复习</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%AF%AD%E4%B9%89%E5%8C%96%E7%9A%84%E4%BD%9C%E7%94%A8"><span class="nav-number">2.2.</span> <span class="nav-text">语义化的作用:</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%B7%A8%E5%9F%9F%E9%97%AE%E9%A2%98"><span class="nav-number">2.3.</span> <span class="nav-text">跨域问题</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%87%AA%E5%AE%9A%E4%B9%89%E6%A0%87%E7%AD%BE"><span class="nav-number">2.4.</span> <span class="nav-text">自定义标签</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8div%E4%BB%A3%E6%9B%BFbutton"><span class="nav-number">2.5.</span> <span class="nav-text">使用div代替button</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#html5%E7%A6%BB%E7%BA%BF%E5%B7%A5%E4%BD%9C"><span class="nav-number">2.6.</span> <span class="nav-text">HTML5离线工作</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day1-2-%E7%90%86%E8%A7%A3css---%E9%9F%A9%E5%B9%BF%E5%86%9B"><span class="nav-number">3.</span> <span class="nav-text">Day1-2 理解CSS - 韩广军</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#css%E7%9A%84%E5%8A%A0%E8%BD%BD%E8%BF%87%E7%A8%8B"><span class="nav-number">3.1.</span> <span class="nav-text">CSS的加载过程</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%80%89%E6%8B%A9%E5%99%A8%E5%A4%8D%E4%B9%A0"><span class="nav-number">3.2.</span> <span class="nav-text">选择器复习</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%A2%9C%E8%89%B2%E8%A1%A8%E7%A4%BA%E5%A4%8D%E4%B9%A0"><span class="nav-number">3.3.</span> <span class="nav-text">颜色表示复习</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AD%97%E4%BD%93%E4%BD%BF%E7%94%A8%E5%A4%8D%E4%B9%A0"><span class="nav-number">3.4.</span> <span class="nav-text">字体使用复习</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8E%9F%E5%AD%90%E5%8C%96csswindi-css"><span class="nav-number">3.5.</span> <span class="nav-text">原子化CSS(Windi CSS)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BC%98%E9%9B%85%E9%99%8D%E7%BA%A7%E4%B8%8E%E6%B8%90%E8%BF%9B%E5%A2%9E%E5%BC%BA"><span class="nav-number">3.6.</span> <span class="nav-text">优雅降级与渐进增强</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#cssinjs"><span class="nav-number">3.7.</span> <span class="nav-text">CSSinJS</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%B8%80%E4%BA%9B%E4%B8%8D%E7%9F%A5%E9%81%93%E7%9A%84%E4%BC%AA%E5%85%83%E7%B4%A0"><span class="nav-number">3.8.</span> <span class="nav-text">一些不知道的伪元素</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day1-3-%E6%B7%B1%E5%85%A5css---%E9%9F%A9%E5%B9%BF%E5%86%9B"><span class="nav-number">4.</span> <span class="nav-text">Day1-3 深入CSS - 韩广军</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BB%A7%E6%89%BF"><span class="nav-number">4.1.</span> <span class="nav-text">继承</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#css%E7%9A%84%E6%B1%82%E5%80%BC%E8%BF%87%E7%A8%8B"><span class="nav-number">4.2.</span> <span class="nav-text">CSS的求值过程</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%83%E5%B1%80"><span class="nav-number">4.3.</span> <span class="nav-text">布局</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day2-%E5%A6%82%E4%BD%95%E5%86%99%E5%A5%BDjs---%E6%9C%88%E5%BD%B1"><span class="nav-number">5.</span> <span class="nav-text">Day2 如何写好JS - 月影</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8E%9F%E5%88%99-%E5%90%84%E5%8F%B8%E5%85%B6%E8%B4%A3"><span class="nav-number">5.1.</span> <span class="nav-text">原则-各司其责</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8E%9F%E5%88%99-%E7%BB%84%E4%BB%B6%E5%B0%81%E8%A3%85"><span class="nav-number">5.2.</span> <span class="nav-text">原则-组件封装</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8E%9F%E5%88%99-%E8%BF%87%E7%A8%8B%E6%8A%BD%E8%B1%A1"><span class="nav-number">5.3.</span> <span class="nav-text">原则-过程抽象</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BC%96%E7%A8%8B%E8%8C%83%E5%BC%8F"><span class="nav-number">5.4.</span> <span class="nav-text">编程范式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AF%E4%BC%98%E7%A7%80%E7%9A%84%E4%BB%A3%E7%A0%81"><span class="nav-number">5.5.</span> <span class="nav-text">什么是优秀的代码</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day3-1-web%E6%A0%87%E5%87%86%E4%B8%8E%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91---%E6%9D%8E%E6%9D%BE%E5%B3%B0"><span class="nav-number">6.</span> <span class="nav-text">Day3-1 Web标准与前端开发 -
李松峰</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day3-2-%E5%89%8D%E7%AB%AF%E8%B0%83%E8%AF%95%E7%9F%A5%E8%AF%86---%E7%A7%83%E5%A4%B4%E6%8A%AB%E9%A3%8E%E4%BE%A0"><span class="nav-number">7.</span> <span class="nav-text">Day3-2 前端调试知识 -
秃头披风侠</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#pc%E7%AB%AF%E8%B0%83%E8%AF%95chrome-dev-tools"><span class="nav-number">7.1.</span> <span class="nav-text">PC端调试(chrome dev-tools)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%A7%BB%E5%8A%A8%E7%AB%AF%E8%B0%83%E8%AF%95"><span class="nav-number">7.2.</span> <span class="nav-text">移动端调试</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day4-1-%E5%93%8D%E5%BA%94%E5%BC%8F%E7%B3%BB%E7%BB%9F%E4%B8%8Ereact---%E7%89%9B%E5%B2%B3"><span class="nav-number">8.</span> <span class="nav-text">Day4-1 响应式系统与React -
牛岳</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#react%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF"><span class="nav-number">8.1.</span> <span class="nav-text">React的设计思路</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#react%E7%9A%84%E5%AE%9E%E7%8E%B0"><span class="nav-number">8.2.</span> <span class="nav-text">React的实现</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#react%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86"><span class="nav-number">8.3.</span> <span class="nav-text">React状态管理</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day4-2-%E5%89%8D%E7%AB%AF%E5%8A%A8%E7%94%BB%E5%AE%9E%E7%8E%B0---%E8%92%8B%E7%BF%94"><span class="nav-number">9.</span> <span class="nav-text">Day4-2 前端动画实现 - 蒋翔</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8A%A8%E7%94%BB%E5%9F%BA%E6%9C%AC%E5%8E%9F%E7%90%86"><span class="nav-number">9.1.</span> <span class="nav-text">动画基本原理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%89%8D%E7%AB%AF%E5%8A%A8%E7%94%BB%E5%88%86%E7%B1%BB"><span class="nav-number">9.2.</span> <span class="nav-text">前端动画分类</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%9E%E7%8E%B0%E5%89%8D%E7%AB%AFjs%E5%8A%A8%E7%94%BB"><span class="nav-number">9.3.</span> <span class="nav-text">实现前端JS动画</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%AE%9E%E8%B7%B5"><span class="nav-number">9.4.</span> <span class="nav-text">实践</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day5-1-http%E5%AE%9E%E7%94%A8%E6%8C%87%E5%8D%97---%E6%9D%A8%E8%B6%85%E7%94%B7"><span class="nav-number">10.</span> <span class="nav-text">Day5-1 HTTP实用指南 - 杨超男</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%A6%82%E8%BF%B0"><span class="nav-number">10.1.</span> <span class="nav-text">概述</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8D%8F%E8%AE%AE%E5%88%86%E6%9E%90"><span class="nav-number">10.2.</span> <span class="nav-text">协议分析</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E8%A7%81%E5%9C%BA%E6%99%AF%E7%9A%84%E5%BA%94%E7%94%A8"><span class="nav-number">10.3.</span> <span class="nav-text">常见场景的应用</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%9B%B4%E5%A4%9A%E7%9A%84%E5%8D%8F%E8%AE%AE"><span class="nav-number">10.4.</span> <span class="nav-text">更多的协议</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day5-2-node.js%E4%B8%8E%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91%E5%AE%9E%E6%88%98---%E6%AC%A7%E9%98%B3%E4%BA%9A%E4%B8%9C"><span class="nav-number">11.</span> <span class="nav-text">Day5-2
Node.js与前端开发实战 - 欧阳亚东</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#nodejs%E8%BF%90%E8%A1%8C%E6%97%B6%E7%BB%93%E6%9E%84"><span class="nav-number">11.1.</span> <span class="nav-text">NodeJS运行时结构</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#nodejs%E8%BF%90%E8%A1%8C%E6%97%B6%E7%89%B9%E7%82%B9"><span class="nav-number">11.2.</span> <span class="nav-text">NodeJS运行时特点</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#node%E5%AE%89%E8%A3%85%E8%B0%83%E8%AF%95%E4%B8%8E%E9%83%A8%E7%BD%B2"><span class="nav-number">11.3.</span> <span class="nav-text">Node安装调试与部署</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day6-1-%E5%88%9D%E8%AF%86webgl---%E6%9C%88%E5%BD%B1"><span class="nav-number">12.</span> <span class="nav-text">Day6-1 初识WebGL - 月影</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day6-2-web%E5%BC%80%E5%8F%91%E7%9A%84%E5%AE%89%E5%85%A8%E4%B9%8B%E6%97%85---%E5%88%98%E5%AE%87%E6%99%A8"><span class="nav-number">13.</span> <span class="nav-text">Day6-2 Web开发的安全之旅 -
刘宇晨</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#xss%E8%B7%A8%E7%AB%99%E8%84%9A%E6%9C%AC%E6%94%BB%E5%87%BB"><span class="nav-number">13.1.</span> <span class="nav-text">XSS跨站脚本攻击</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#xss%E6%94%BB%E5%87%BB%E7%9A%84%E9%98%B2%E5%BE%A1"><span class="nav-number">13.2.</span> <span class="nav-text">XSS攻击的防御</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#csrf%E8%B7%A8%E7%AB%99%E4%BC%AA%E9%80%A0%E8%AF%B7%E6%B1%82"><span class="nav-number">13.3.</span> <span class="nav-text">CSRF跨站伪造请求</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#csrf%E9%98%B2%E5%BE%A1"><span class="nav-number">13.4.</span> <span class="nav-text">CSRF防御</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%B3%A8%E5%85%A5%E6%94%BB%E5%87%BB"><span class="nav-number">13.5.</span> <span class="nav-text">注入攻击</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%B3%A8%E5%85%A5%E9%98%B2%E5%BE%A1"><span class="nav-number">13.6.</span> <span class="nav-text">注入防御</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#dos%E6%8B%92%E7%BB%9D%E6%9C%8D%E5%8A%A1%E6%94%BB%E5%87%BB"><span class="nav-number">13.7.</span> <span class="nav-text">DoS拒绝服务攻击</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#dos%E9%98%B2%E5%BE%A1"><span class="nav-number">13.8.</span> <span class="nav-text">DoS防御</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day7-%E6%9E%84%E5%BB%BAwebpack%E7%9F%A5%E8%AF%86%E4%BD%93%E7%B3%BB---%E8%8C%83%E6%96%87%E6%9D%B0"><span class="nav-number">14.</span> <span class="nav-text">Day7 构建webpack知识体系 -
范文杰</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BB%80%E4%B9%88%E6%98%AFwebpack"><span class="nav-number">14.1.</span> <span class="nav-text">什么是Webpack</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#webpack%E6%89%93%E5%8C%85%E6%B5%81%E7%A8%8B"><span class="nav-number">14.2.</span> <span class="nav-text">Webpack打包流程</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8webpack"><span class="nav-number">14.3.</span> <span class="nav-text">使用Webpack</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#loader%E7%BB%84%E4%BB%B6"><span class="nav-number">14.4.</span> <span class="nav-text">Loader组件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#plugin%E7%BB%84%E4%BB%B6"><span class="nav-number">14.5.</span> <span class="nav-text">Plugin组件</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A6%82%E4%BD%95%E5%AD%A6%E4%B9%A0webpack"><span class="nav-number">14.6.</span> <span class="nav-text">如何学习Webpack</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day8-1-typescript%E5%85%A5%E9%97%A8---%E6%9E%97%E7%9A%87"><span class="nav-number">15.</span> <span class="nav-text">Day8-1 TypeScript入门 - 林皇</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#js%E4%B8%8Ets"><span class="nav-number">15.1.</span> <span class="nav-text">JS与TS</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%9F%BA%E7%A1%80%E8%AF%AD%E6%B3%95"><span class="nav-number">15.2.</span> <span class="nav-text">基础语法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E9%AB%98%E7%BA%A7%E7%B1%BB%E5%9E%8B"><span class="nav-number">15.3.</span> <span class="nav-text">高级类型</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E4%BD%BF%E7%94%A8"><span class="nav-number">15.4.</span> <span class="nav-text">使用</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day8-2-%E5%B0%8F%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91---ycaptain"><span class="nav-number">16.</span> <span class="nav-text">Day8-2 小游戏开发 - ycaptain</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%89%8D%E7%AB%AF%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91"><span class="nav-number">16.1.</span> <span class="nav-text">前端游戏开发</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E8%A7%81%E5%BC%95%E6%93%8E"><span class="nav-number">16.2.</span> <span class="nav-text">常见引擎</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#pixijsweb%E8%BF%9B%E8%A1%8C%E6%B8%B8%E6%88%8F%E5%BC%80%E5%8F%91"><span class="nav-number">16.3.</span> <span class="nav-text">PixiJS+Web进行游戏开发</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day9-1-%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%8A%80%E6%9C%AF%E5%85%A8%E8%A7%A3---%E5%BC%A0%E6%99%93%E4%BC%9F"><span class="nav-number">17.</span> <span class="nav-text">Day9-1 小程序技术全解 -
张晓伟</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%8F%E7%A8%8B%E5%BA%8F%E4%B8%9A%E5%8A%A1%E4%BB%B7%E5%80%BC"><span class="nav-number">17.1.</span> <span class="nav-text">小程序业务价值</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%8E%9F%E7%90%86"><span class="nav-number">17.2.</span> <span class="nav-text">小程序原理</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%8F%E7%A8%8B%E5%BA%8F%E8%AF%AD%E6%B3%95"><span class="nav-number">17.3.</span> <span class="nav-text">小程序语法</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E8%B7%A8%E7%AB%AF%E6%9E%B6%E6%9E%84"><span class="nav-number">17.4.</span> <span class="nav-text">跨端架构</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day9-2-%E5%89%8D%E7%AB%AF%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%BA%94%E7%94%A8---%E5%90%B4%E7%AB%8B%E5%AE%81"><span class="nav-number">18.</span> <span class="nav-text">Day9-2 前端设计模式应用 -
吴立宁</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%B5%8F%E8%A7%88%E5%99%A8%E4%B8%AD%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%8D%95%E4%BE%8B%E5%8F%91%E5%B8%83%E8%AE%A2%E9%98%85"><span class="nav-number">18.1.</span> <span class="nav-text">浏览器中的设计模式(单例&amp;发布订阅)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#js%E4%B8%AD%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E5%8E%9F%E5%9E%8B%E4%BB%A3%E7%90%86%E6%A8%A1%E5%BC%8F"><span class="nav-number">18.2.</span> <span class="nav-text">JS中的设计模式(原型&amp;代理模式)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%89%8D%E7%AB%AF%E6%A1%86%E6%9E%B6%E4%B8%AD%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%A8%A1%E5%BC%8F%E4%BB%A3%E7%90%86%E7%BB%84%E5%90%88%E6%A8%A1%E5%BC%8F"><span class="nav-number">18.3.</span> <span class="nav-text">前端框架中的设计模式(代理&amp;组合模式)</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E6%80%BB%E7%BB%93"><span class="nav-number">18.4.</span> <span class="nav-text">总结</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day10-1-web%E5%A4%9A%E5%AA%92%E4%BD%93%E5%85%A5%E9%97%A8---%E5%88%98%E7%AB%8B%E5%9B%BD"><span class="nav-number">19.</span> <span class="nav-text">Day10-1 Web多媒体入门 -
刘立国</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E7%BC%96%E7%A0%81%E6%A0%BC%E5%BC%8F"><span class="nav-number">19.1.</span> <span class="nav-text">编码格式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B0%81%E8%A3%85%E6%A0%BC%E5%BC%8F"><span class="nav-number">19.2.</span> <span class="nav-text">封装格式</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%A4%9A%E5%AA%92%E4%BD%93%E5%85%83%E7%B4%A0%E5%92%8C%E6%89%A9%E5%B1%95api"><span class="nav-number">19.3.</span> <span class="nav-text">多媒体元素和扩展API</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%B8%B8%E8%A7%81%E6%B5%81%E5%AA%92%E4%BD%93%E5%8D%8F%E8%AE%AE"><span class="nav-number">19.4.</span> <span class="nav-text">常见流媒体协议</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%BA%94%E7%94%A8%E5%9C%BA%E6%99%AF"><span class="nav-number">19.5.</span> <span class="nav-text">应用场景</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#day10-2-%E6%95%B0%E6%8D%AE%E5%8F%AF%E8%A7%86%E5%8C%96%E5%9F%BA%E7%A1%80---%E4%BD%95%E8%8F%B2%E8%8F%B2"><span class="nav-number">20.</span> <span class="nav-text">Day10-2 数据可视化基础 -
何菲菲</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%AF%E8%A7%86%E5%8C%96%E7%9A%84%E5%8E%9F%E5%88%99%E4%B8%8E%E5%B8%B8%E8%A7%81%E9%94%99%E8%AF%AF"><span class="nav-number">20.1.</span> <span class="nav-text">可视化的原则与常见错误</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%AF%E8%A7%86%E5%8C%96%E8%AF%84%E4%BB%B7%E6%A8%A1%E5%9E%8B"><span class="nav-number">20.2.</span> <span class="nav-text">可视化评价模型</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#%E5%8F%AF%E8%A7%86%E5%8C%96%E5%B7%A5%E5%85%B7"><span class="nav-number">20.3.</span> <span class="nav-text">可视化工具</span></a></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author site-overview-item animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Liu Kairui"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">Liu Kairui</p>
  <div class="site-description" itemprop="description">LiuKairui Persional Website</div>
</div>
<div class="site-state-wrap site-overview-item animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">45</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">24</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
          <a href="/tags/">
        <span class="site-state-item-count">53</span>
        <span class="site-state-item-name">标签</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author site-overview-item animated">
      <span class="links-of-author-item">
        <a href="https://github.com/KairuiLiu" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;KairuiLiu" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:tclkr@live.com" title="E-Mail → mailto:tclkr@live.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://qm.qq.com/cgi-bin/qm/qr?k=oaf3ToOlN17hr5sHV98bT8qxsNYGaw5L&noverify=0" title="QQ → https:&#x2F;&#x2F;qm.qq.com&#x2F;cgi-bin&#x2F;qm&#x2F;qr?k&#x3D;oaf3ToOlN17hr5sHV98bT8qxsNYGaw5L&amp;noverify&#x3D;0" rel="noopener" target="_blank"><i class="fab fa-qq fa-fw"></i>QQ</a>
      </span>
      <span class="links-of-author-item">
        <a href="/atom.xml" title="RSS → &#x2F;atom.xml"><i class="fa fa-rss fa-fw"></i>RSS</a>
      </span>
      <span class="links-of-author-item">
        <a href="https://liukairui.blog.csdn.net/" title="CSDN → https:&#x2F;&#x2F;liukairui.blog.csdn.net" rel="noopener" target="_blank"><i class="fab fa-cuttlefish fa-fw"></i>CSDN</a>
      </span>
      <span class="links-of-author-item">
        <a href="http://liukairui.cc/" title="国内站点 → http:&#x2F;&#x2F;liukairui.cc" rel="noopener" target="_blank"><i class="fa fa-globe fa-fw"></i>国内站点</a>
      </span>
  </div>
  <div class="cc-license site-overview-item animated" itemprop="license">
    <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" class="cc-opacity" rel="noopener" target="_blank"><img src="https://cdnjs.cloudflare.com/ajax/libs/creativecommons-vocabulary/2020.11.3/assets/license_badges/small/by_nc_sa.svg" alt="Creative Commons"></a>
  </div>


  <div class="links-of-blogroll site-overview-item animated">
    <div class="links-of-blogroll-title"><i class="fa fa-link fa-fw"></i>
      友情链接
    </div>
    <ul class="links-of-blogroll-list">
        <li class="links-of-blogroll-item">
          <a href="https://paste.ubuntu.com/" title="https:&#x2F;&#x2F;paste.ubuntu.com&#x2F;" rel="noopener" target="_blank">Ubuntu Pastebin</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://send.firefox.com/" title="https:&#x2F;&#x2F;send.firefox.com&#x2F;" rel="noopener" target="_blank">Firefox Send</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://jkwzs.cn/" title="https:&#x2F;&#x2F;jkwzs.cn&#x2F;" rel="noopener" target="_blank">南花醉笔丶の个人博客</a>
        </li>
        <li class="links-of-blogroll-item">
          <a href="https://ywrby.cn/" title="https:&#x2F;&#x2F;ywrby.cn&#x2F;" rel="noopener" target="_blank">Ywrby个人博客</a>
        </li>
    </ul>
  </div>

        </div>
      </div>
    </div>
  </aside>
  <div class="sidebar-dimmer"></div>


    </header>

    
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="Liu Kairui">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="LiuKairui Website">
      <meta itemprop="description" content="LiuKairui Persional Website">
    </span>
    
    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="2022寒假字节跳动前端训练营笔记 | LiuKairui Website">
      <meta itemprop="description" content="参加了字节跳动前端训练营,开个文章记录下新学到的东西">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          2022寒假字节跳动前端训练营笔记
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2022-01-16 03:12:20" itemprop="dateCreated datePublished" datetime="2022-01-16T03:12:20+08:00">2022-01-16</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%89%8D%E7%AB%AF/" itemprop="url" rel="index"><span itemprop="name">前端</span></a>
        </span>
    </span>

  
    <span id="/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/" class="post-meta-item leancloud_visitors" data-flag-title="2022寒假字节跳动前端训练营笔记" title="阅读次数">
      <span class="post-meta-item-icon">
        <i class="far fa-eye"></i>
      </span>
      <span class="post-meta-item-text">阅读次数：</span>
      <span class="leancloud-visitors-count"></span>
    </span>
  
  <span class="post-meta-item">
    
    <span class="post-meta-item-icon">
      <i class="far fa-comment"></i>
    </span>
    <span class="post-meta-item-text">Valine：</span>
  
    <a title="valine" href="/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/#valine-comments" itemprop="discussionUrl">
      <span class="post-comments-count valine-comment-count" data-xid="/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/" itemprop="commentCount"></span>
    </a>
  </span>
  
  

<script>
    CONFIG.hostname = location.hostname;
</script>
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>76k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>1:09</span>
    </span>
</div>

            <div class="post-description">参加了字节跳动前端训练营,开个文章记录下新学到的东西</div>
        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">
        <p>已经完成的部分</p>
<ul>
<li>Day02 如何写好JS - 月影</li>
<li>Day04-2 前端动画实现 - 蒋翔</li>
<li>Day08-1 TypeScript入门 - 林皇</li>
<li>Day09-2 前端设计模式应用 - 吴立宁</li>
<li>Day04-1 响应式系统与React - 牛岳</li>
<li>Day06-2 Web开发的安全之旅 - 刘宇晨</li>
<li>Day01-1 前端与HTML - 韩广军</li>
<li>Day01-2 理解CSS - 韩广军</li>
<li>Day01-3 深入CSS - 韩广军</li>
<li>Day10-1 Web多媒体入门 - 刘立国</li>
<li>Day07 构建webpack知识体系 - 范文杰</li>
<li>Day05-1 HTTP实用指南 - 杨超男</li>
<li>Day03-2 前端调试知识 - 秃头披风侠</li>
<li>Day06-1 初识WebGL - 月影</li>
<li>Day05-2 Node.js与前端开发实战 - 欧阳亚东</li>
<li>Day09-1 小程序技术全解 - 张晓伟</li>
<li>Day08-2 小游戏开发 - ycaptain</li>
<li>Day03-1 Web标准与前端开发 - 李松峰</li>
<li>Day10-2 数据可视化基础 - 何菲菲</li>
</ul>
<h3 id="day0-字节笔试">Day0 字节笔试</h3>
<ul>
<li><p>不定项选择:JS基础, 事件冒泡等内容</p></li>
<li><p>编程题</p>
<blockquote>
<p>判断输入的字符串是不是4的整数幂</p>
</blockquote>
<p>标准解法当然是位运算, 我比较懒, 读取数字,
求<code>log(t)/log(4)</code>是不是整数,
其实应该用<code>algorithm</code>库中更快速的的<code>log_2()</code>,
无奈在牛客的代码提示中没找到这个函数</p>
<blockquote>
<p>输入一个字符串, 输出全排列</p>
</blockquote>
<p>标准解法当时是搜索/康托, 我比较懒,
直接调<code>std::next_permutation(begin, end)</code></p></li>
</ul>
<h3 id="day1-1-前端与html---韩广军">Day1-1 前端与HTML - 韩广军</h3>
<p>前端职责:图形界面下的人机交互问题</p>
<p><strong>前端技术栈</strong></p>
<ul>
<li>HTML:结构</li>
<li>CSS:样式</li>
<li>JS:交互</li>
<li>http协议:传输</li>
</ul>
<p><strong>前端需要关注问题</strong></p>
<ul>
<li>美观</li>
<li>功能</li>
<li>无障碍(不只是对于残障人士, 还包括一些困难的场景, 例如:
在抖动的环境下按一个小按钮)</li>
<li>安全</li>
<li>兼容性</li>
<li>用户体验</li>
</ul>
<p><strong>前端可以实现的功能</strong></p>
<ul>
<li>服务端(Node.JS)</li>
<li>用户端(Election)</li>
<li>3D(webGL)</li>
<li>语音交互(webRTC)</li>
<li>代码执行(WebAssembly)</li>
</ul>
<p><strong>HTML是什么</strong></p>
<ul>
<li>HyperText: 图片, 标签, 音视频</li>
<li>Markup Language: 标签, 属性键值</li>
</ul>
<p><strong>HTML语法</strong></p>
<ul>
<li>不区分大小写(推荐小写)</li>
<li>空标签可以不闭合或者加<code>/</code>闭合(<code>&lt;input&gt;</code>,<code>&lt;img /&gt;</code>)</li>
<li>属性值用双引号闭合</li>
<li>部分标签属性值可以省略(required, readonly...)</li>
</ul>
<p>浏览器拿到HTML后会将嵌套关系转化为一个DOM树</p>
<h4 id="html标签复习">HTML标签复习</h4>
<ul>
<li><code>&lt;!doctype html&gt;</code>:
指明HTML版本(不写的话浏览器按照老版本标准(兼容模式)执行)</li>
<li><code>&lt;html&gt;</code>根标签</li>
<li><code>&lt;head&gt;</code>存放元数据</li>
<li><code>&lt;body&gt;</code>需要呈现的内容</li>
<li>标题:
<code>&lt;h1/&gt;</code>-<code>&lt;h6/&gt;</code>默认样式从大到小</li>
<li>列表:
<ul>
<li>有序列表 <pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ol</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ol</span><span class="token punctuation">></span></span></code></pre></li>
<li>无序列表 <pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>ul</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>1<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>2<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>li</span><span class="token punctuation">></span></span>3<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>li</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>ul</span><span class="token punctuation">></span></span></code></pre></li>
<li>定义列表(注意,支持多对多) <pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dl</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dt</span><span class="token punctuation">></span></span>导演<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dt</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dd</span><span class="token punctuation">></span></span>陈凯歌<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dd</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dt</span><span class="token punctuation">></span></span>主演<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dt</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dd</span><span class="token punctuation">></span></span>张国荣<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dd</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dd</span><span class="token punctuation">></span></span>张丰毅<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dd</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dt</span><span class="token punctuation">></span></span>出品<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dt</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dt</span><span class="token punctuation">></span></span>宣发<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dt</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>dd</span><span class="token punctuation">></span></span>巩俐<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dd</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>dl</span><span class="token punctuation">></span></span></code></pre>
<dl>
<dt>
导演
</dt>
<dd>
陈凯歌
</dd>
<dt>
主演
</dt>
<dd>
张国荣
</dd>
<dd>
张丰毅
</dd>
<dt>
出品
</dt>
<dt>
宣发
</dt>
<dd>
巩俐
</dd>
</dl></li>
</ul></li>
<li>链接:<code>&lt;a href="" target="" /&gt;</code>最重要的两个属性是<code>href</code>与<code>target</code></li>
<li>多媒体:
<code>&lt;img/&gt;,&lt;audio&gt;&lt;/auduio&gt;,&lt;video&gt;&lt;/video&gt;</code>
<ul>
<li>alt: 不被加载的时候的替换内容(不被加载的情况包括: 加载失败,
用户开启省流模式)</li>
<li>音视频自动播放属性:
<ul>
<li>autoplay: 如果用户之前访问过这个域名,
还手动播放该域名下的视频过才会自动播放</li>
<li>controls: 规定浏览器应该为视频提供播放控件</li>
<li>muted: 静音播放</li>
</ul></li>
<li>音视频自动播放属性:
<ul>
<li>视频静音(通过加上 muted 属性)或音量设置为 0</li>
<li>用户与网站进行了交互(通过点击, 敲击, 按键等)</li>
<li>站点已被列入浏览器白名单;</li>
<li>浏览器确定用户频繁使用媒体,
自动加入白名单或者通过首选项或其他用户界面功能手动发生</li>
<li>自动播放功能策略授予了<code>&lt;iframe&gt;</code>及其文档自动播放支持.</li>
<li>用户已将该站点添加到其移动设备的主屏幕或在桌面设备上安装了 PWA.</li>
</ul></li>
</ul></li>
<li>输入:
<ul>
<li><p><code>&lt;input placeholder="" type=""/&gt;</code></p>
<ul>
<li><code>type="range"</code><input placeholder="" type="range"/></li>
<li><code>type= "number"</code><input placeholder="" type="number"/></li>
<li><code>type= "date"</code><input placeholder="" type="date"/></li>
<li><code>type= "checkbox"</code><input placeholder="" type="checkbox"/>
通过name进行分组互斥, 通过<code>&lt;label for=""&gt;</code>打标记</li>
<li><code>type= "radio"</code><input placeholder="" type="radio"/>
通过name进行分组互斥, 通过<code>&lt;label for=""&gt;</code>打标记</li>
<li><code>type= "select"</code>下拉框 <select> <option>Apple</option>
<option>Orange</option> <option>Pineapple</option>
<option>Banana</option> </select> <pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>select</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span><span class="token punctuation">></span></span>Apple<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>option</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span><span class="token punctuation">></span></span>Orange<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>option</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span><span class="token punctuation">></span></span>Pineapple<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>option</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span><span class="token punctuation">></span></span>Banana<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>option</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>select</span><span class="token punctuation">></span></span></code></pre></li>
</ul></li>
<li><p>可选下拉列表输入框(可以选择,也可以随便输入内容,如果输入的是选项的前缀会自动跳出提示)
<input list="ice-cream-flavors" id="ice-cream-choice" name="ice-cream-choice" /></p>
<p><datalist id="ice-cream-flavors"> <option value="Chocolate">
<option value="Coconut"> <option value="Mint">
<option value="Strawberry"> <option value="Vanilla"> </datalist></p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">list</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ice-cream-flavors<span class="token punctuation">"</span></span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ice-cream-choice<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ice-cream-choice<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>datalist</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>ice-cream-flavors<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Chocolate<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Coconut<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Mint<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Strawberry<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>option</span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Vanilla<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>datalist</span><span class="token punctuation">></span></span></code></pre></li>
<li><p>多行输入框: <code>&lt;textarea&gt;&lt;/textarea&gt;</code></p>
<textarea></textarea></li>
</ul></li>
<li>文本标签
<ul>
<li>引用
<ul>
<li>块级别引用:
<code>&lt;blockquote cite=""&gt;&lt;/blockquote&gt;</code></li>
<li>短引用:
<code>&lt;cite&gt;&lt;/cite&gt;</code>(一般写一些作品名)</li>
<li>引用之前页面中的内容<code>&lt;q&gt;&lt;/q&gt;</code></li>
</ul></li>
<li>代码
<ul>
<li>单行代码<code>&lt;code&gt;&lt;/code&gt;</code></li>
<li>多行代码<code>&lt;pre&gt;&lt;code&gt;&lt;/code&gt;&lt;/pre&gt;</code></li>
</ul></li>
<li>强调
<ul>
<li><code>&lt;strong&gt;&lt;/strong&gt;</code>表示语意上重要 紧急</li>
<li><code>&lt;em&gt;&lt;/em&gt;</code>语气上的重读</li>
</ul></li>
</ul></li>
<li>版块划分
<ul>
<li>页头
<ul>
<li>header</li>
<li>nav</li>
</ul></li>
<li>主体
<ul>
<li>main</li>
</ul></li>
<li>与内容相关但不属于主体内容的(信息推荐, 广告): aside</li>
<li>页尾: <code>&lt;footer&gt;&lt;/footer&gt;</code></li>
</ul></li>
</ul>
<h4 id="语义化的作用">语义化的作用:</h4>
<ul>
<li>开发者:方便修改与维护</li>
<li>浏览器:展示页面</li>
<li>搜索引擎:提取关键词, 排序</li>
<li>屏幕阅读器</li>
</ul>
<h4 id="跨域问题">跨域问题</h4>
<p><code>&lt;script&gt;</code>, <code>&lt;a&gt;</code>是完全支持跨域的,
在Chrome97中https页面不能跨域引用来自http页面的图片等资源</p>
<h4 id="自定义标签">自定义标签</h4>
<p><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Web_Components">webComponment</a>是一套不同的技术,
允许您创建可重用的定制元素(它们的功能封装在您的代码之外)并且在您的web应用中使用它们.</p>
<ul>
<li>目的: 实现复杂HTML组件的复用</li>
<li>技术组成:
<ul>
<li>Custom elements(自定义元素)</li>
<li>Shadow DOM(影子DOM)</li>
<li>HTML templates(HTML模板)</li>
</ul></li>
</ul>
<p><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_shadow_DOM"><strong>shadow
DOM</strong></a></p>
<p>shadow
DOM允许在文档流中创建一些<strong>完全独立于其他DOM的子DOM树</strong>(不会使用页面的JS/CSS,
在DevTools中现实的也是#shadowDOM字样).
于是我们可以封装一个具有独立功能的组件,
并完全不会干扰其他DOM与被其他DOM干扰. 在shadow
DOM内部我们可以定义元素的样式与行为</p>
<p>有这样的术语</p>
<ul>
<li>Shadow host: Shadow DOM挂载到的DOM节点.</li>
<li>Shadow tree: Shadow DOM内部的DOM树.</li>
<li>Shadow boundary: Shadow DOM结束的地方, 也是常规 DOM开始的地方.</li>
<li>Shadow root: Shadow tree的根节点.</li>
</ul>
<p>方法</p>
<ul>
<li><code>Element.attachShadow()</code>: 将一个 shadow root
附加到任何一个元素上.
它接受一个配置对象<code>&#123;mode: 'open'|'closed'&#125;</code>分别表示这个DOM是否可以被页面的JS抓取</li>
</ul>
<p><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_templates_and_slots"><strong>HTML
templates&amp;slots</strong></a></p>
<p>类似于响应式框架中的模板, 开发者通过模板来复用一些 HTML 代码段, 在
HTML5 标准下我们甚至不需要 javascript 框架就能轻松使用模板.</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>template</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my-paragraph<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>My paragraph<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>template</span><span class="token punctuation">></span></span></code></pre>
<p>在模板中创建 HTML 代码块和子 DOM 树,
使得我们可以用不同的物理文件来组织代码.
通过<code>&lt;link&gt;</code>标签来引入这些文件,
link到的数据并不会展示到DOM, 需要手动添加</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>head</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>link</span> <span class="token attr-name">rel</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>import<span class="token punctuation">"</span></span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>components/some.html<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>head</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>
    <span class="token comment">&lt;!--some DOM--></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>my-paragraph</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my-paragraph<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>my-paragraph</span><span class="token punctuation">></span></span>
    <span class="token comment">&lt;!--some DOM--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span></code></pre>
<p>还可以通过<code>slots</code>增加灵活性: 也有默认插槽, 具名插槽等.
见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Web_Components/Using_templates_and_slots#%E4%BD%BF%E7%94%A8%E6%A7%BDslots_%E6%B7%BB%E5%8A%A0%E7%81%B5%E6%B4%BB%E5%BA%A6">MDN</a></p>
<p><a
target="_blank" rel="noopener" href="https://ruanyifeng.com/blog/2017/06/custom-elements.html"><strong>Custom
elements</strong></a></p>
<p>我们声明一个语义化的自定义元素来引用组件, 用 javascript
建立自定义元素和模板, shadow DOM 之间的关联,
然后将自定义标签插入到页面上就能得到一个封装好的组件.</p>
<blockquote>
<p>"自定义元素的名字必须包含一个破折号(<code>-</code>)所以<code>&lt;x-tags&gt;</code>,
<code>&lt;my-element&gt;</code>和<code>&lt;my-awesome-app&gt;</code>都是正确的名字,
而<code>&lt;tabs&gt;</code>和<code>&lt;foo_bar&gt;</code>是不正确的.
这样的限制使得 HTML 解析器可以分辨那些是标准元素, 哪些是自定义元素.
"</p>
</blockquote>
<p>浏览器提供了两种类型对象<code>HTMLUnknownElement</code>和<code>HTMLElement</code></p>
<ul>
<li>HTML标准元素在浏览器中会被解析为<code>HTMLElement</code>实例</li>
<li>用户没有声明的自定义元素会被解析为<code>HTMLUnknownElement</code></li>
<li>一旦自定义元素中使用了破折号此时自定义元素就变为了<code>HTMLElement</code></li>
</ul>
<p>使用</p>
<p><pre class="language-javascript" data-language="javascript"><code class="language-javascript"><span class="token comment">// 定义一个 &lt;my-element>&lt;/my-element></span>
<span class="token keyword">class</span> <span class="token class-name">MyElement</span> <span class="token keyword">extends</span> <span class="token class-name">HTMLElement</span> <span class="token punctuation">&#123;</span><span class="token operator">...</span><span class="token punctuation">&#125;</span>
window<span class="token punctuation">.</span>customElements<span class="token punctuation">.</span><span class="token function">define</span><span class="token punctuation">(</span><span class="token string">'my-element'</span><span class="token punctuation">,</span> MyElement<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<p>上面代码中,
原生的<code>window.customElements</code>对象的<code>define</code>方法用来定义
Custom Element. 该方法接受两个参数, 第一个参数是自定义元素的名字,
第二个参数是一个 ES6 的<code>class</code>.</p>
<p>这个<code>class</code>使用<code>get</code>和<code>set</code>方法定义
Custom Element 的某个属性.</p>
<p><pre class="language-javascript" data-language="javascript"><code class="language-javascript"><span class="token keyword">class</span> <span class="token class-name">MyElement</span> <span class="token keyword">extends</span> <span class="token class-name">HTMLElement</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">get</span> <span class="token function">content</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getAttribute</span><span class="token punctuation">(</span><span class="token string">'content'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>

  <span class="token keyword">set</span> <span class="token function">content</span><span class="token punctuation">(</span><span class="token parameter">val</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setAttribute</span><span class="token punctuation">(</span><span class="token string">'content'</span><span class="token punctuation">,</span> val<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>有了这个定义,
网页之中就可以插入<code>&lt;my-element&gt;</code>了.</p>
<p><pre class="language-markdown" data-language="markdown"><code class="language-markdown"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>my-element</span> <span class="token attr-name">content</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>Custom Element<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  Hello
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>my-element</span><span class="token punctuation">></span></span></code></pre></p>
<h4 id="使用div代替button">使用div代替button</h4>
<p>可以这么代替, 但是不仅要复刻样式,
还要加入属性<code>role="button"</code>方便浏览器赋予聚焦等属性与无障碍优化(<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Accessibility/ARIA">Aria</a>,<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/Accessibility/ARIA/Roles/button_role">Roles</a>)</p>
<h4 id="html5离线工作">HTML5离线工作</h4>
<ul>
<li>前端缓存方案: <code>localStorage</code>,
<code>sessionStorage</code></li>
<li>使用<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Service_Worker_API">Service
Worker</a>进行离线后行为管理与通信</li>
</ul>
<p>Service workers 本质上充当 Web 应用程序,
浏览器与网络(可用时)之间的代理服务器. 这个 API 旨在创建有效的离线体验,
它会拦截网络请求并根据网络是否可用来采取适当的动作,
更新来自服务器的的资源. 它还提供入口以推送通知和访问后台同步 API.
Service workers 是基于 HTTPS 的, 因为Service Worker中涉及到请求拦截,
所以必须使用HTTPS协议来保障安全.</p>
<p>Service workers生命周期</p>
<ul>
<li><p>注册: 要使用Service Worker, 首先需要注册一个sw,
通知浏览器为该页面分配一块内存, 然后sw就会进入安装阶段.</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">(</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token string">'serviceWorker'</span> <span class="token keyword">in</span> navigator<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        navigator<span class="token punctuation">.</span>serviceWorker<span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token string">'./sw.js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">(</span><span class="token punctuation">)</span>

<span class="token comment">// 只针对部分页面进行注册</span>
navigator<span class="token punctuation">.</span>serviceWorker<span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token string">'/topics/sw.js'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// 另一种作用域限定</span>
navigator<span class="token punctuation">.</span>serviceWorker<span class="token punctuation">.</span><span class="token function">register</span><span class="token punctuation">(</span><span class="token string">'sw.js'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">scope</span><span class="token operator">:</span> <span class="token string">'./'</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>安装: sw开始缓存文件了, 检查所有文件的缓存状态, 如果都已经缓存了,
则安装成功, 进入下一阶段.</p></li>
<li><p>激活: 如果是第一次加载sw, 在安装后, 会直接进入activated阶段,
而如果sw进行更新, 情况就会显得复杂一些(新版本安装, 老版本工作 -
新版本开始waiting, 等待老版本terminated - 新版本替换)</p></li>
<li><p>空闲: 空闲状态一般是不可见的,
这种一般说明sw的事情都处理完毕了,然后处于闲置状态了,浏览器会周期性的轮询,
去释放处于idle的sw占用的资源</p></li>
<li><p>终止: 终止状态一般触发条件由下面几种方式</p>
<ol type="1">
<li>关闭浏览器一段时间</li>
<li>手动清除serviceworker</li>
<li>在sw安装时直接跳过waiting阶段</li>
</ol>
<pre class="language-javascript" data-language="javascript"><code class="language-javascript">self<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'install'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">event</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">//跳过等待过程</span>
    self<span class="token punctuation">.</span><span class="token function">skipWaiting</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>拦截:
sw最终要和关键阶段,主要用于拦截代理所有指定的请求,然后进行二次相应的处理操作</p></li>
</ul>
<h3 id="day1-2-理解css---韩广军">Day1-2 理解CSS - 韩广军</h3>
<p><strong>CSS</strong>: Cascading Style Sheets 层叠样式表,
用来定义页面元素的样式</p>
<p><strong>使用CSS的三种方法</strong>:
外链,嵌入,内联(组件式开发看起来是新的模式)</p>
<h4 id="css的加载过程">CSS的加载过程</h4>
<pre class="mermaid">graph LR
加载HTML --> 解析HTML --> 创建DOM树  
解析HTML --> 加载CSS --> 解析CSS --> 创建DOM树 --> 渲染展示页面</pre>
<h4 id="选择器复习">选择器复习</h4>
<ul>
<li>通配选择器<code>*</code></li>
<li>标签选择器<code>tagName</code></li>
<li>id选择器<code>#id</code></li>
<li>类选择器<code>.class</code></li>
<li>属性选择器
<ul>
<li>没有值只有键<code>[disabled]</code></li>
<li>完全匹配值<code>[type="pwd"]</code></li>
<li>开头<code>[type^="pwd"]</code></li>
<li>结尾<code>[type$="pwd"]</code></li>
</ul></li>
<li>伪类选择器
<ul>
<li>状态伪类:a有LVHA,在按下后有:force状态(LVFHA)</li>
<li>结构伪类:first-child...</li>
</ul></li>
<li>选择器组合
<ul>
<li><code>AB</code>同时满足AB</li>
<li><code>A B</code>选择<code>B</code>如果<code>B</code>是<code>A</code>的子孙</li>
<li><code>A&gt;B</code>选择<code>B</code>如果<code>B</code>是<code>A</code>的子元素</li>
<li><code>A~B</code>选择<code>B</code>如果<code>B</code>在<code>A</code>后且与<code>A</code>同级</li>
<li><code>A+B</code>选择<code>B</code>如果他紧随在<code>A</code>后面</li>
</ul></li>
</ul>
<h4 id="颜色表示复习">颜色表示复习</h4>
<ul>
<li>RGB: 三原色混合, RGB值的变化不能直观表示颜色的变化,
不方面操作颜色</li>
<li>HSL: 更加直观方便操作
<ul>
<li>Hue: 色相, 表示颜色基本属性, 值为0-360表示色环上的色值</li>
<li>Saturation: 饱和度, 表示颜色的鲜艳程度, 值为0-100%, 越高越鲜艳,
越低越灰</li>
<li>Lightness: 亮度, 值为0-100%,
越高越白越低越灰(例如想要让btn变灰只需要调低L)</li>
</ul></li>
<li>alpha透明度: 可以与rgb/hsl组成rgba/hsla,
值为0-1/映射到0-255后转Hex</li>
</ul>
<h4 id="字体使用复习">字体使用复习</h4>
<p><code>font-family</code>: 指定使用的字体组合,
由于浏览器使用字体基于用户安装, 所以要多指定几组,
并且在最后使用字体类型兜底,
例如<code>font-family:'Segoe UI', Tahoma, sans-serif</code></p>
<p><strong>字体类型</strong></p>
<ul>
<li>serif: 衬线字体, 在字末尾有一定装饰(Georgia, 宋体)</li>
<li>sans-serif: 无衬线字体, 线条单一, 末尾没有装饰(Arial, Helvetica,
黑体)</li>
<li>cursive: 手写体(Caflisch Script, 楷体)</li>
<li>fantasy: 艺术体</li>
<li>monosapce: 等宽字体(Consolas, Courier, 中文字体)</li>
</ul>
<p>在使用<code>font-family</code>的时候注意</p>
<ul>
<li>一般在font-family最后指定一个字体类型兜底</li>
<li>先英文后中文, 原因是浏览器在渲染字符的时候会逐字符比对使用的字体,
一般中文字体中就包含了英文字体, 如果中文在前,
为英文字体准备的字体就不会匹配了</li>
</ul>
<p><strong>使用自定义字体</strong></p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css">
  <span class="token atrule"><span class="token rule">@font-face</span></span> <span class="token punctuation">&#123;</span>
    <span class="token property">font-family</span><span class="token punctuation">:</span> f1<span class="token punctuation">;</span>
    <span class="token property">src</span><span class="token punctuation">:</span> <span class="token url"><span class="token function">url</span><span class="token punctuation">(</span><span class="token string url">"//s2.ssl.qhimg.com/static/ff00cb8151eeecd2.woff2"</span><span class="token punctuation">)</span></span> <span class="token function">format</span><span class="token punctuation">(</span><span class="token string">"woff2"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span> <span class="token special-attr"><span class="token attr-name">style</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value css language-css"><span class="token property">font-family</span><span class="token punctuation">:</span> f1<span class="token punctuation">,</span> serif</span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>落霞与孤鹜齐飞, 秋水共长天一色. <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span></code></pre>
<p>对于英文字符这这种方法可以快速引入字体, 但是对于中文字符来说,
中文字体包太大了, 一般需要裁剪字体包获得需要的字符</p>
<p><strong>字体样式</strong></p>
<ul>
<li><code>font-size</code>: 设置字体大小
<ul>
<li>关键字: small medium large</li>
<li>长度单位: px em</li>
<li>百分数: 相对于父元素字体大小</li>
</ul></li>
<li><code>font-style</code>: 设置字体风格
<ul>
<li><code>normal</code>: 正常</li>
<li><code>italic</code>: 斜体</li>
<li><code>oblique</code>: 倾斜</li>
</ul></li>
<li><code>font-weight</code>: 设置字重
<ul>
<li>关键字: normal, bold...</li>
<li>数值: 100-900(400=normal,700=bold),
如果系统中找不到字体则会就近替换</li>
</ul></li>
<li><code>line-height</code>: 设置行高(baseline之间的距离)</li>
<li><code>font</code>: 字体设置简写([斜体] 粗细 大小[/行高]
[字体族])</li>
</ul>
<p><strong>段落属性</strong></p>
<ul>
<li><code>text-align</code>: 对齐方式
left|center|right|justify(分散对齐, 且仅对非最后一行有效,
如果文字只有一行那也不生效)</li>
<li><code>letter-spacing: Xpx</code> 字符之间的距离</li>
<li><code>word-spacing: Xpx</code> 字符之间的距离</li>
<li><code>text-indent: Xpx</code> 首行缩进(支持负数)</li>
<li><code>text-decoration: underline|line-through|overline|none</code>
下划线, 删除线, 上划线, 无</li>
<li><code>white-space</code>:
normal(默认)|nowrap(不换行)|pre(保留所有换行与空格)|pre-wrap(保留空格,
会换行)|pre-wrap(合并空格, 保留换行)</li>
</ul>
<h4 id="原子化csswindi-css">原子化CSS(Windi CSS)</h4>
<blockquote>
<p>原子化 CSS 是一种 CSS 的架构方式, 它倾向于小巧且用途单一的 class,
并且会以视觉效果进行命名</p>
</blockquote>
<p>CSS原子化是一种写法, 其特点就是一个类名对应一个样式,
从而通过在标签上附加不同的类名来生成对应的效果,
可以有效的减少CSS的相关代码, 例如</p>
<pre class="language-css" data-language="css"><code class="language-css"><span class="token selector">.flex</span> <span class="token punctuation">&#123;</span>
    <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p><strong>坏处</strong></p>
<ol type="1">
<li>需要定制一大堆工具类, 这些使用的话需要开发人员的熟悉.</li>
<li>虽然减少了CSS的代码, 但是使得HTML的代码变得更臃肿了.</li>
<li>CSS 规则插入顺序仍然很重要.</li>
</ol>
<p><strong>好处</strong></p>
<ol type="1">
<li>写法真的变简单了, 比如添加一个常用的规则时, 直接就加原子类</li>
<li>原子类是全局的, 所以当我们移动一段标签到其他页面时,
样式也就是有的</li>
<li>当我们使用原子类的时候,
我们修改页面的样式时往往不会再去修改<code>CSS</code>代码了,
而是直接修改原子类名</li>
</ol>
<p><strong>框架</strong>: <code>tailwindcss</code></p>
<blockquote>
<p>Tailwind CSS 是一个功能类优先的 CSS 框架, 它集成了诸如
<code>flex</code>, <code>pt-4</code>, <code>text-center</code> 和
<code>rotate-90</code> 这样的的类, 它们能直接在脚本标记语言中组合起来,
构建出任何设计.</p>
</blockquote>
<p>是不是就是CSS原子类的写法了？当然, <code>tailwindcss</code>不止于此,
它还有很多强大的功能和配置</p>
<p><a target="_blank" rel="noopener" href="https://zhuanlan.zhihu.com/p/425814828">参考</a></p>
<h4 id="优雅降级与渐进增强">优雅降级与渐进增强</h4>
<p>CSS构建的两种观点</p>
<ul>
<li>"优雅降级"观点<br />
"优雅降级"观点认为应该针对那些最高级, 最完善的浏览器来设计网站.
而将那些被认为"过时"或有功能缺失的浏览器下的测试工作安排在开发周期的最后阶段,
并把测试对象限定为主流浏览器(如 IE, Mozilla 等)的前一个版本.
在这种设计范例下, 旧版的浏览器被认为仅能提供"简陋却无妨 (poor, but
passable)" 的浏览体验. 你可以做一些小的调整来适应某个特定的浏览器.
但由于它们并非我们所关注的焦点, 因此除了修复较大的错误之外,
其它的差异将被直接忽略.</li>
<li>"渐进增强"观点<br />
"渐进增强"观点则认为应关注于内容本身. 内容是我们建立网站的诱因.
有的网站展示它, 有的则收集它, 有的寻求, 有的操作,
还有的网站甚至会包含以上的种种, 但相同点是它们全都涉及到内容.
这使得"渐进增强"成为一种更为合理的设计范例. 这也是它立即被 Yahoo!
所采纳并用以构建其"分级式浏览器支持 (Graded Browser
Support)"策略的原因所在.</li>
</ul>
<pre class="language-css" data-language="css"><code class="language-css"><span class="token selector">.transition</span> <span class="token punctuation">&#123;</span> <span class="token comment">/*渐进增强写法*/</span>
  <span class="token property">-webkit-transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
     <span class="token property">-moz-transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
       <span class="token property">-o-transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
          <span class="token property">transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token selector">.transition</span> <span class="token punctuation">&#123;</span> <span class="token comment">/*优雅降级写法*/</span>
          <span class="token property">transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
       <span class="token property">-o-transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
     <span class="token property">-moz-transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
  <span class="token property">-webkit-transition</span><span class="token punctuation">:</span> all .5s<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<h4 id="cssinjs">CSSinJS</h4>
<p>CSS默认是全局生效的, 可以使用CSS in JS, scoped等方案实现, CSS in
JS是一种CSS工程化方案</p>
<p>传统CSS问题</p>
<ul>
<li><strong>全局污染</strong> - CSS的选择器是全局生效的,
所以在class名称比较简单时, 容易引起全局选择器冲突,
导致样式互相影响.</li>
<li><strong>命名混乱</strong> - 因为怕全局污染,
所以日常起class名称时会尽量加长, 这样不容易重复, 但当项目由多人维护时,
很容易导致命名风格不统一.</li>
<li><strong>样式重用困难</strong> -
有时虽然知道项目上已有一些相似的样式, 但因为怕互相影响, 不敢重用.</li>
<li><strong>代码冗余</strong> - 由于样式重用的困难性等问题,
导致代码冗余.</li>
</ul>
<p>为解决问题而提出的规范</p>
<ul>
<li><strong>SASS, LESS</strong> - 提供了变量, 简单函数, 运算, 继承等,
扩展性, 重用性都有了很大的提升, 解决了一些样式重用冗余的问题,
但是对于命名混乱问题的效果不大.</li>
<li>**BEM (.block__element--modifier)** - 比较流行的class命名规则,
部分解决了命名混乱和全局污染的问题, 但class定义起来还是不太方便,
比较冗长, 而且和第三方库的命名还是有可能冲突.</li>
<li><strong>CSS Modules</strong> - 模块化CSS,
将CSS文件<code>import</code>到JavaScript里并声明为字符串,
在使用的时候拼串导出. 基本上解决了全局污染, 命名混乱,
样式重用和冗余的问题, 但CSS有嵌套结构的限制(只能一层),
也无法方便的在CSS和JavaScript之间共享变量.</li>
</ul>
<p>CSS in JS就是将应用的CSS样式写在JavaScript文件里面,
可以利用标签的<code>style</code>拼串,
也可以利用<code>ele.style</code>实现</p>
<p><a
target="_blank" rel="noopener" href="http://ruanyifeng.com/blog/2017/04/css_in_js.html">见此</a></p>
<h4 id="一些不知道的伪元素">一些不知道的伪元素</h4>
<ul>
<li><code>::first-letter</code>: 首字母</li>
<li><code>::first-line</code>: 首行</li>
<li><code>::cue (:cue)</code>: 用于选中VTT视频中的怪东西</li>
<li><code>::selection</code>: 选中被用户高亮的/选中的内容</li>
<li><code>::slotted()</code>: 选中HTML模板元素</li>
</ul>
<p>见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/Pseudo-elements">MDN</a></p>
<h3 id="day1-3-深入css---韩广军">Day1-3 深入CSS - 韩广军</h3>
<p>CSS选择器的特异程度:
<code>ID选择器数目_(伪)类选择器数目_标签选择器数目</code>拼串</p>
<h4 id="继承">继承</h4>
<p>部分属性可以自动继承其来自父元素的计算值, 除非显式指定</p>
<ul>
<li>可以继承的样式: 与文字相关的</li>
<li>不可以继承的属性: 宽度, 高度, 盒子模型, 尺寸相关,
<strong>对于不可继承的属性可以通过<code>key:inherit</code></strong>继承</li>
<li>如果元素想要继承的值父元素们都没有, 那么其会自动使用默认值.
<strong>可以使用<code>key:initial</code>显式使用默认值</strong></li>
<li>还可以使用<code>key:unset</code>, 若该CSS属性可继承,
则从父级继承对应属性值, 若该CSS性不可继承, 则将其重置为初始值</li>
</ul>
<h4 id="css的求值过程">CSS的求值过程</h4>
<pre class="mermaid">graph LR
  DOM(DOM树) --> filtering
  样式规则(样式规则) --> filtering --声明值--> cascading --层叠值--> defauting --指定值--> resolving --计算值--> formatting --使用值--> constraining --> 实际值(实际值)</pre>
<ol type="1">
<li>filtering: 找到可以匹配到元素的规则</li>
<li>cascading: 根据选择器特异性找到优先级最高的属性值</li>
<li>defauting: 对于没有匹配到的属性值, 要么继承父类, 要么使用默认值</li>
<li>resolving: 将相对值(red, rm)转化为浏览器下的值(#f00, px),
这一部分不转换需要部署才知道的值(<code>em</code>可以转为<code>px</code>,
<code>width:60%</code>需要布局后才知道是多少, 在这一步不转化),
<strong>此处得到的结果叫计算值,
子元素样式为inherit的时候就是参考了父元素的计算值</strong></li>
<li>formatting: 将相对值进一步转化(例如<code>width:60%</code>)</li>
<li>constraining: 将小数像素转化为整数像素,
并根据特殊规则进行调整(<code>min-width</code>,
chrome中的<code>font-size:10px</code>会转化为<code>12px</code>)最终应用在页面上</li>
</ol>
<h4 id="布局">布局</h4>
<p><strong>布局相关技术</strong></p>
<ul>
<li>常规流(文档流)
<ul>
<li>行级</li>
<li>块级</li>
<li>表格布局</li>
<li>FlexBox</li>
<li>Grid布局</li>
</ul></li>
<li>浮动</li>
<li>绝对定位</li>
</ul>
<p><strong>盒子模型</strong></p>
<p>当padding设置为百分比的时候padding参考的是父元素的<strong>宽度</strong></p>
<p>据此实现一个1:1的盒子</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>style</span><span class="token punctuation">></span></span><span class="token style"><span class="token language-css">
  <span class="token selector">.wap</span><span class="token punctuation">&#123;</span>
    <span class="token property">width</span><span class="token punctuation">:</span> 200px<span class="token punctuation">;</span>
    <span class="token property">height</span><span class="token punctuation">:</span> 300px<span class="token punctuation">;</span>
    <span class="token property">background-color</span><span class="token punctuation">:</span> #bfa<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token selector">.cont</span><span class="token punctuation">&#123;</span>
    <span class="token property">width</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
    <span class="token property">height</span><span class="token punctuation">:</span> 0<span class="token punctuation">;</span>
    <span class="token property">padding-bottom</span><span class="token punctuation">:</span> 100%<span class="token punctuation">;</span>
    <span class="token property">background-color</span><span class="token punctuation">:</span> red<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
</span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>style</span><span class="token punctuation">></span></span>

<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>body</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>wap<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>cont<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>body</span><span class="token punctuation">></span></span></code></pre>
<p>当margin设置为百分比的时候padding参考的是父元素的<strong>宽度</strong></p>
<p>垂直方向margin会合并折叠</p>
<p><strong>块级元素与行内元素</strong></p>
<ul>
<li>块级元素不能并排摆放, 适用所有盒模型</li>
<li>行内元素可以与其他行内元素拜访, 但是盒模型width, height不适用</li>
<li>inline-block本身是行内元素, 但是被放在了盒子中, 适用盒模型width,
height</li>
</ul>
<p><strong>Flex Box</strong></p>
<ul>
<li><code>flex-dirextion: row|row-reverse|column|column-reverse</code>:
摆放流向</li>
<li><code>justify-content: flex-start|flex-end|center|space-between|space-around|space-evenly</code>:
主轴对齐方式</li>
<li><code>align-items: flex-start|flex-end|center|stretch|baseline</code>侧轴对齐</li>
<li><code>align-self</code>: 为特定元素设置侧轴对齐方式</li>
<li><code>order</code>: 手动指定顺序</li>
<li><code>flex-grow</code>: 当容器有剩余空间的时候的伸展能力</li>
<li><code>flex-shrink</code>:
当容器剩余空间不足的时候的压缩能力(<strong>默认是1</strong>)</li>
<li><code>flex-base</code>: 容器的自然长度</li>
<li><code>flex</code>: 缩写
<ul>
<li>单值语法: 值必须为以下其中之一:
<ul>
<li>一个无单位数(<code>&lt;number&gt;</code>):
它会被当作flex:<code>&lt;number&gt;</code> 1 0;
<code>&lt;flex-shrink&gt;</code>的值被假定为1,
然后<code>&lt;flex-basis&gt;</code> 的值被假定为0.</li>
<li>一个有效的宽度(width)值: 它会被当作
<code>&lt;flex-basis&gt;</code>的值.<br />
</li>
<li>关键字none, auto或initial.</li>
</ul></li>
<li>双值语法: 第一个值必须为一个无单位数, 并且它会被当作
<code>&lt;flex-grow&gt;</code> 的值. 第二个值必须为以下之一:
<ul>
<li>一个无单位数:它会被当作 <code>&lt;flex-shrink&gt;</code> 的值.</li>
<li>一个有效的宽度值: 它会被当作 <code>&lt;flex-basis&gt;</code>
的值.</li>
</ul></li>
<li>三值语法:
<ul>
<li>第一个值必须为一个无单位数, 并且它会被当作
<code>&lt;flex-grow&gt;</code> 的值.</li>
<li>第二个值必须为一个无单位数, 并且它会被当作
<code>&lt;flex-shrink&gt;</code> 的值.</li>
<li>第三个值必须为一个有效的宽度值, 并且它会被当作
<code>&lt;flex-basis&gt;</code> 的值. <pre class="language-css" data-language="css"><code class="language-css"><span class="token comment">/* 一个值, 无单位数字: flex-grow */</span>
<span class="token property">flex</span><span class="token punctuation">:</span> 2<span class="token punctuation">;</span>

<span class="token comment">/* 一个值, width/height: flex-basis */</span>
<span class="token property">flex</span><span class="token punctuation">:</span> 10em<span class="token punctuation">;</span>
<span class="token property">flex</span><span class="token punctuation">:</span> 30px<span class="token punctuation">;</span>
<span class="token property">flex</span><span class="token punctuation">:</span> min-content<span class="token punctuation">;</span>

<span class="token comment">/* 两个值: flex-grow | flex-basis */</span>
<span class="token property">flex</span><span class="token punctuation">:</span> 1 30px<span class="token punctuation">;</span>

<span class="token comment">/* 两个值: flex-grow | flex-shrink */</span>
<span class="token property">flex</span><span class="token punctuation">:</span> 2 2<span class="token punctuation">;</span>

<span class="token comment">/* 三个值: flex-grow | flex-shrink | flex-basis */</span>
<span class="token property">flex</span><span class="token punctuation">:</span> 2 2 10%<span class="token punctuation">;</span>

<span class="token comment">/*全局属性值 */</span>
<span class="token property">flex</span><span class="token punctuation">:</span> inherit<span class="token punctuation">;</span>
<span class="token property">flex</span><span class="token punctuation">:</span> initial<span class="token punctuation">;</span>
<span class="token property">flex</span><span class="token punctuation">:</span> unset<span class="token punctuation">;</span></code></pre></li>
</ul></li>
</ul></li>
</ul>
<p><strong>Grid 布局</strong></p>
<ul>
<li>使用<code>display: grid</code>创建网格容器</li>
<li>使用<code>grid-template-X</code>: 将容器划分为网格</li>
<li>设置每一个子元素占用那些行列</li>
<li>使用<code>grid-area: X/X/X/X</code>或<code>grid-column/row-start/end</code>指定元素所占位置,
允许重叠</li>
</ul>
<p><strong>Float 布局</strong></p>
<p>本质是做图文环绕的, 在没有先进布局的时候还用来做各种布局,
现在已经不需要float做布局了, 除了图文环绕, 其他不需要用float做</p>
<p><strong>Position</strong></p>
<ul>
<li><code>static</code>: 默认</li>
<li><code>relative</code>: 相对元素本身定位</li>
<li><code>absolute</code>: 相对非<code>static</code>祖先定位</li>
<li><code>fixed</code>: 相对于视口定位</li>
</ul>
<h3 id="day2-如何写好js---月影">Day2 如何写好JS - 月影</h3>
<h4 id="原则-各司其责">原则-各司其责</h4>
<p>我们希望让HTML, CSS, JS分别去控制结构, 表现, 功能.
各司其职并不是让他们物理上分类(写成三个文件),
而是让他们功能上分离(要不然现在组件化开发岂不是完全违反了原则),
例如不要让JS去直接操作CSS样式</p>
<p>举例: 请实现一个静态页面的深夜模式</p>
<ul>
<li><p>最基础的版本</p>
<p><pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>modeBtn<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>🌞<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">></span></span>深夜食堂<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">></span></span></code></pre></p>
<p><pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> btn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'modeBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
btn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> body <span class="token operator">=</span> document<span class="token punctuation">.</span>body<span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>innerHTML <span class="token operator">===</span> <span class="token string">'🌞'</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    body<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">'black'</span><span class="token punctuation">;</span>
    body<span class="token punctuation">.</span>style<span class="token punctuation">.</span>color <span class="token operator">=</span> <span class="token string">'white'</span><span class="token punctuation">;</span>
    e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">'🌜'</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
    body<span class="token punctuation">.</span>style<span class="token punctuation">.</span>backgroundColor <span class="token operator">=</span> <span class="token string">'white'</span><span class="token punctuation">;</span>
    body<span class="token punctuation">.</span>style<span class="token punctuation">.</span>color <span class="token operator">=</span> <span class="token string">'black'</span><span class="token punctuation">;</span>
    e<span class="token punctuation">.</span>target<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">'🌞'</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<p>有问题: 通过文字判断状态, 使用JS直接操作了一个CSS样式</p></li>
<li><p>改一改</p>
<p><pre class="language-css" data-language="css"><code class="language-css"><span class="token selector">body.night</span> <span class="token punctuation">&#123;</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span>
  <span class="token property">transition</span><span class="token punctuation">:</span> all 1s<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">#modeBtn::after</span> <span class="token punctuation">&#123;</span>
  <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">'🌞'</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
<span class="token selector">body.night #modeBtn::after</span> <span class="token punctuation">&#123;</span>
  <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">'🌜'</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p><pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> btn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'modeBtn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
btn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">e</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> body <span class="token operator">=</span> document<span class="token punctuation">.</span>body<span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>body<span class="token punctuation">.</span>className <span class="token operator">!==</span> <span class="token string">'night'</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    body<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'night'</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
    body<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p>
<p>定义了该<code>night</code>样式, 不用通过文字判断状态了.
要是让我写我最多改成<code>classList.toggle()</code></p></li>
<li><p>回头想想: 我们在做什么事情?
我们在做一个<strong>纯视觉效果展示</strong>, 样式应该是CSS控制的!
JS是控制行为的, 我们可以尝试纯CSS+HTML实现</p>
<p><pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>modeCheckBox<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>checkbox<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>content<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>header</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>label</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>modeBtn<span class="token punctuation">"</span></span> <span class="token attr-name">for</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>modeCheckBox<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>label</span><span class="token punctuation">></span></span>
		<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>h1</span><span class="token punctuation">></span></span>深夜食堂<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>h1</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>header</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre></p>
<p><pre class="language-css" data-language="css"><code class="language-css"><span class="token selector">#modeCheckBox</span> <span class="token punctuation">&#123;</span>
  <span class="token property">display</span><span class="token punctuation">:</span> none<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">#modeCheckBox:checked + .content</span> <span class="token punctuation">&#123;</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> black<span class="token punctuation">;</span>
  <span class="token property">color</span><span class="token punctuation">:</span> white<span class="token punctuation">;</span>
  <span class="token property">transition</span><span class="token punctuation">:</span> all 1s<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">#modeBtn</span> <span class="token punctuation">&#123;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 2rem<span class="token punctuation">;</span>
  <span class="token property">float</span><span class="token punctuation">:</span> right<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">#modeBtn::after</span> <span class="token punctuation">&#123;</span>
  <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">'🌞'</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">#modeCheckBox:checked + .content #modeBtn::after</span> <span class="token punctuation">&#123;</span>
  <span class="token property">content</span><span class="token punctuation">:</span> <span class="token string">'🌜'</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></p>
<p>直接使用<code>checkbox</code>用于点击,
通过选择<code>checkbox</code>的<code>checked</code>伪类来定义夜间模式</p>
<p>要是之和我这么一说, 我估计要这么写</p>
<p><pre class="language-diff" data-language="diff"><code class="language-diff"><span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> &lt;input id="modeCheckBox" type="checkbox">
</span></span><span class="token deleted-arrow deleted"><span class="token prefix deleted">&lt;</span><span class="token line">div class="content">
</span></span>	&lt;header>
<span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line">	    &lt;input id="modeCheckBox" type="checkbox">
</span></span>	    &lt;label id="modeBtn" for="modeCheckBox">&lt;/label>
		&lt;h1>深夜食堂&lt;/h1>
	&lt;/header>
<span class="token deleted-arrow deleted"><span class="token prefix deleted">&lt;</span><span class="token line">/div></span></span></code></pre></p>
<p><pre class="language-diff" data-language="diff"><code class="language-diff">#modeCheckBox &#123;
<span class="token deleted-sign deleted"><span class="token prefix deleted">-</span><span class="token line"> display: none;
</span></span><span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> outline: none;
</span><span class="token prefix inserted">+</span><span class="token line"> width: 0;
</span><span class="token prefix inserted">+</span><span class="token line"> height: 0;
</span></span>&#125;

// ...</code></pre></p>
<p>很自然的, 我把<code>input</code>与<code>label</code>放一起了,
然后把在关掉<code>checkbox</code>的样式, 但是这不符合语义化要求啊!!!,
回头想想, 为啥要专门有个<code>label</code>标签呢?
为的是让他们永远在一起吗? 当然是可以让这两个标签分开啊</p>
<p>人家还可以把这个<code>checkbox</code>给删掉, 太他妈牛了.
这才是语义化, <strong>样式与表现各司其职</strong></p></li>
</ul>
<p>我们学到了</p>
<ul>
<li>什么是HTML, CSS, JS各司其职</li>
<li>不要让JS直接干预Style</li>
<li>用class表示状态</li>
<li>对于样式的展示尽量寻求零JS方案</li>
</ul>
<h4 id="原则-组件封装">原则-组件封装</h4>
<p>我们希望从Web页面中抽象出一个一个包含HTML, CSS, JS的组件出来,
使得组件具备良好的封装性, 正确性, 可扩展性, 复用性.
我们将通过封装一个轮播图组件来了解组件封装的过程</p>
<ol type="1">
<li><p>结构设计:</p>
<p>轮播图显然是一个列表结构, 使用<code>ul</code>即可</p></li>
<li><p>样式设计:</p>
<p>使用CSS绝对定位将图片重叠在一起, 使用修饰符定义active元素,
使用transition切换动画</p></li>
<li><p>行为设计-API设计(功能设计):</p>
<p>应该保证API是: 原子操作, 职责单一, 满足灵活性</p>
<p>我们设计一个<code>Slide</code>类</p>
<p><pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">Slider</span><span class="token punctuation">&#123;</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">id</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>			
    <span class="token keyword">this</span><span class="token punctuation">.</span>container <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container
    <span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.slider-list__item, .slider-list__item--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">getSelectedItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>		<span class="token comment">// 活动元素</span>
    <span class="token keyword">const</span> selected <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container
      <span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slider-list__item--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> selected
  <span class="token punctuation">&#125;</span>
  <span class="token function">getSelectedItemIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>	<span class="token comment">// 活动元素index</span>
    <span class="token keyword">return</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSelectedItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">slideTo</span><span class="token punctuation">(</span><span class="token parameter">idx</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>				<span class="token comment">// 滚到</span>
    <span class="token keyword">const</span> selected <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSelectedItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>selected<span class="token punctuation">)</span><span class="token punctuation">&#123;</span> 
      selected<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slider-list__item'</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">const</span> item <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>item<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
      item<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slider-list__item--selected'</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>				<span class="token comment">// 下一个</span>
    <span class="token keyword">const</span> currentIdx <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSelectedItemIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> nextIdx <span class="token operator">=</span> <span class="token punctuation">(</span>currentIdx <span class="token operator">+</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token operator">%</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span>nextIdx<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">slidePrevious</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>			<span class="token comment">// 上一个</span>
    <span class="token keyword">const</span> currentIdx <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">getSelectedItemIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">const</span> previousIdx <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span>length <span class="token operator">+</span> currentIdx <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">)</span>
      <span class="token operator">%</span> <span class="token keyword">this</span><span class="token punctuation">.</span>items<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span>previousIdx<span class="token punctuation">)</span><span class="token punctuation">;</span>  
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> slider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Slider</span><span class="token punctuation">(</span><span class="token string">'my-slider'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
slider<span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span><span class="token number">3</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></p></li>
<li><p>行为设计-控制流</p>
<p>组件应该是在DOM上可控制的(总不能让用户输入<code>slider.slideNext</code>切换吧),
我们需要完成DOM状态与API行为的耦合</p>
<p>我们可以通过自定义事件进行解耦(尽量让DOM状态的改变与我们的代码之间独立)</p>
<p>为<code>Slide</code>类加入<code>start</code>与<code>stop</code>实现控制,
在构造函数中加入控制器的时间绑定</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">Slider</span><span class="token punctuation">&#123;</span>
    
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">id<span class="token punctuation">,</span> cycle <span class="token operator">=</span> <span class="token number">3000</span></span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.slider-list__item, .slider-list__item--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>cycle <span class="token operator">=</span> cycle<span class="token punctuation">;</span>

    <span class="token keyword">const</span> controller <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>controller<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> buttons <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control-buttons, .slide-list__control-buttons--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      controller<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseover'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
        <span class="token keyword">const</span> idx <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>buttons<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>evt<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>idx <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span>idx<span class="token punctuation">)</span><span class="token punctuation">;</span>
          <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
      controller<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseout'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      
      <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'slide'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">const</span> idx <span class="token operator">=</span> evt<span class="token punctuation">.</span>detail<span class="token punctuation">.</span>index
        <span class="token keyword">const</span> selected <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control-buttons--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>selected<span class="token punctuation">)</span> selected<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slide-list__control-buttons'</span><span class="token punctuation">;</span>
        buttons<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slide-list__control-buttons--selected'</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
    
    <span class="token keyword">const</span> previous <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__previous'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>previous<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
      previous<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slidePrevious</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        evt<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    
    <span class="token keyword">const</span> next <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__next'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
      next<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        evt<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span>
    
  <span class="token function">getSelectedItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">/*...*/</span><span class="token punctuation">&#125;</span>
  <span class="token function">getSelectedItemIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">/*...*/</span><span class="token punctuation">&#125;</span>
  <span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">/*...*/</span><span class="token punctuation">&#125;</span>
  <span class="token function">slidePrevious</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token comment">/*...*/</span><span class="token punctuation">&#125;</span>
  
  <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>_timer <span class="token operator">=</span> <span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">,</span> <span class="token keyword">this</span><span class="token punctuation">.</span>cycle<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token function">clearInterval</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>_timer<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> slider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Slider</span><span class="token punctuation">(</span><span class="token string">'my-slider'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>组件的改进</p>
<p>轮播图已经实现, 但是不具备很好的扩展性与复用性.
我们希望模块进行改进</p>
<ul>
<li><p>插件化-解耦</p>
<p>从第三四步我们知道模块设计应该考虑API与控制流两个部分,
API主要考虑的是模块的功能, 而控制流主要考虑的是模块的状态控制与展示交互,
在上面的代码中这两部分是紧耦合的(都在构造函数里面). 我们希望</p>
<ul>
<li>控制器(例如轮播图的下一页按钮)部分抽离出来, 做成一个插件</li>
<li>插件与组件之间通过依赖注入的方式建立联系</li>
</ul>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">Slider</span><span class="token punctuation">&#123;</span>
  
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">id<span class="token punctuation">,</span> cycle <span class="token operator">=</span> <span class="token number">3000</span></span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.slider-list__item, .slider-list__item--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>cycle <span class="token operator">=</span> cycle<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
    
  <span class="token function">registerPlugins</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>plugins</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    plugins<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">plugin</span> <span class="token operator">=></span> <span class="token function">plugin</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
    
  <span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token parameter">type<span class="token punctuation">,</span> handler</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span>type<span class="token punctuation">,</span> handler<span class="token punctuation">)</span>
  <span class="token punctuation">&#125;</span>
    
  <span class="token function">getSelectedItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
  <span class="token function">getSelectedItemIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
  <span class="token function">slideTo</span><span class="token punctuation">(</span><span class="token parameter">idx</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
  <span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
  <span class="token function">slidePrevious</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
  <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span>
  <span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span> 
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">pluginController</span><span class="token punctuation">(</span><span class="token parameter">slider</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> controller <span class="token operator">=</span> slider<span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>controller<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">const</span> buttons <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control-buttons, .slide-list__control-buttons--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    controller<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseover'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> idx <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>buttons<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>evt<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span>idx <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
        slider<span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span>idx<span class="token punctuation">)</span><span class="token punctuation">;</span>
        slider<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    controller<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseout'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
      slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    slider<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'slide'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> idx <span class="token operator">=</span> evt<span class="token punctuation">.</span>detail<span class="token punctuation">.</span>index
      <span class="token keyword">const</span> selected <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control-buttons--selected'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span>selected<span class="token punctuation">)</span> selected<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slide-list__control-buttons'</span><span class="token punctuation">;</span>
      buttons<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slide-list__control-buttons--selected'</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>  
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">pluginPrevious</span><span class="token punctuation">(</span><span class="token parameter">slider</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> previous <span class="token operator">=</span> slider<span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__previous'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>previous<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    previous<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      slider<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      slider<span class="token punctuation">.</span><span class="token function">slidePrevious</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      evt<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>  
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">pluginNext</span><span class="token punctuation">(</span><span class="token parameter">slider</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> next <span class="token operator">=</span> slider<span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__next'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>next<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    next<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token parameter">evt</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      slider<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      slider<span class="token punctuation">.</span><span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      evt<span class="token punctuation">.</span><span class="token function">preventDefault</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>  
<span class="token punctuation">&#125;</span>


<span class="token keyword">const</span> slider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Slider</span><span class="token punctuation">(</span><span class="token string">'my-slider'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
slider<span class="token punctuation">.</span><span class="token function">registerPlugins</span><span class="token punctuation">(</span>pluginController<span class="token punctuation">,</span> pluginPrevious<span class="token punctuation">,</span> pluginNext<span class="token punctuation">)</span><span class="token punctuation">;</span>
slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><strong>插件实际上就是一个个函数, 我们让组件暴露一个注册插件的API,
在内部将组件传入插件函数, 我们在插件中获取控制器,
并将绑定控制器行为到组件API</strong></p></li>
<li><p>模板化</p>
<p>实现插件化之后我们只需要修改组件引入的插件就可以实现功能的扩展,
但是还有问题</p>
<ul>
<li>在实际操作的时候我们可能还需要对对应的HTML样式进行修改(例如我们不想要下一张图按键的时候就需要删除那个按钮的HTML与下一张图的插件),</li>
<li>数据不够抽象, 我们的图片是通过HTML加载的, 如果有一天我们想换图片了,
我们就要该HTML</li>
<li><strong>我们想将HTML模板化,
可以为每个组件与插件实现一个render渲染函数</strong></li>
</ul>
<p>对于轮播图, 我考虑: 组件的render方法实现图片结构的加载,
插件的render方法实现对应控制按钮的加载</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>my-slider<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>slider-list<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>div</span><span class="token punctuation">></span></span></code></pre>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">Slider</span> <span class="token punctuation">&#123;</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">id<span class="token punctuation">,</span> opts <span class="token operator">=</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">images</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token literal-property property">cycle</span><span class="token operator">:</span> <span class="token number">3000</span> <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>options <span class="token operator">=</span> opts<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>items <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span>
      <span class="token string">'.slider-list__item, .slider-list__item--selected'</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>cycle <span class="token operator">=</span> opts<span class="token punctuation">.</span>cycle <span class="token operator">||</span> <span class="token number">3000</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span><span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>

  <span class="token comment">// 组件的render</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">const</span> images <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>options<span class="token punctuation">.</span>images<span class="token punctuation">;</span>
    <span class="token keyword">const</span> content <span class="token operator">=</span> images<span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">image</span><span class="token punctuation">)</span> <span class="token operator">=></span>
      <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
      &lt;li class="slider-list__item">
        &lt;img src="</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>image<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">"/>
      &lt;/li>    
    </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
    <span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">&lt;ul></span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>content<span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">&lt;/ul></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>

  <span class="token function">registerPlugins</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>plugins</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    plugins<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">plugin</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token comment">// 创建控制器</span>
      <span class="token keyword">const</span> pluginContainer <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'div'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      pluginContainer<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'.slider-list__plugin'</span><span class="token punctuation">;</span>
      pluginContainer<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> plugin<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>options<span class="token punctuation">.</span>images<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">// 插入控制器</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>pluginContainer<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token comment">// 绑定控制器行为</span>
      plugin<span class="token punctuation">.</span><span class="token function">action</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>

  <span class="token function">getSelectedItem</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">getSelectedItemIndex</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">slideTo</span><span class="token punctuation">(</span><span class="token parameter">idx</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">slideNext</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">slidePrevious</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token parameter">type<span class="token punctuation">,</span> handler</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/*...*/</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> pluginController <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 渲染器返回模板</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">images</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
      &lt;div class="slide-list__control">
        </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>images
          <span class="token punctuation">.</span><span class="token function">map</span><span class="token punctuation">(</span>
            <span class="token punctuation">(</span><span class="token parameter">image<span class="token punctuation">,</span> i</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
            &lt;span class="slide-list__control-buttons</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>
              i <span class="token operator">===</span> <span class="token number">0</span> <span class="token operator">?</span> <span class="token string">'--selected'</span> <span class="token operator">:</span> <span class="token string">''</span>
            <span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">">&lt;/span>
         </span><span class="token template-punctuation string">`</span></span>
          <span class="token punctuation">)</span>
          <span class="token punctuation">.</span><span class="token function">join</span><span class="token punctuation">(</span><span class="token string">''</span><span class="token punctuation">)</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">
      &lt;/div>    
    </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">.</span><span class="token function">trim</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token comment">// 绑定行为</span>
  <span class="token function">action</span><span class="token punctuation">(</span><span class="token parameter">slider</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">const</span> controller <span class="token operator">=</span> slider<span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'.slide-list__control'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

    <span class="token keyword">if</span> <span class="token punctuation">(</span>controller<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> buttons <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">querySelectorAll</span><span class="token punctuation">(</span>
        <span class="token string">'.slide-list__control-buttons, .slide-list__control-buttons--selected'</span>
      <span class="token punctuation">)</span><span class="token punctuation">;</span>
      controller<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseover'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">const</span> idx <span class="token operator">=</span> Array<span class="token punctuation">.</span><span class="token function">from</span><span class="token punctuation">(</span>buttons<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">indexOf</span><span class="token punctuation">(</span>evt<span class="token punctuation">.</span>target<span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>idx <span class="token operator">>=</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
          slider<span class="token punctuation">.</span><span class="token function">slideTo</span><span class="token punctuation">(</span>idx<span class="token punctuation">)</span><span class="token punctuation">;</span>
          slider<span class="token punctuation">.</span><span class="token function">stop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      controller<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'mouseout'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

      slider<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'slide'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">const</span> idx <span class="token operator">=</span> evt<span class="token punctuation">.</span>detail<span class="token punctuation">.</span>index<span class="token punctuation">;</span>
        <span class="token keyword">const</span> selected <span class="token operator">=</span> controller<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span>
          <span class="token string">'.slide-list__control-buttons--selected'</span>
        <span class="token punctuation">)</span><span class="token punctuation">;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span>selected<span class="token punctuation">)</span> selected<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slide-list__control-buttons'</span><span class="token punctuation">;</span>
        buttons<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'slide-list__control-buttons--selected'</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> pluginPrevious <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">/* ... */</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> pluginNext <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">/* ... */</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> slider <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Slider</span><span class="token punctuation">(</span><span class="token string">'my-slider'</span><span class="token punctuation">,</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">images</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token string">'https://p5.ssl.qhimg.com/t0119c74624763dd070.png'</span><span class="token punctuation">,</span>
    <span class="token string">'https://p4.ssl.qhimg.com/t01adbe3351db853eb3.jpg'</span><span class="token punctuation">,</span>
    <span class="token string">'https://p2.ssl.qhimg.com/t01645cd5ba0c3b60cb.jpg'</span><span class="token punctuation">,</span>
    <span class="token string">'https://p4.ssl.qhimg.com/t01331ac159b58f5478.jpg'</span><span class="token punctuation">,</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token literal-property property">cycle</span><span class="token operator">:</span> <span class="token number">3000</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

slider<span class="token punctuation">.</span><span class="token function">registerPlugins</span><span class="token punctuation">(</span>pluginController<span class="token punctuation">,</span> pluginPrevious<span class="token punctuation">,</span> pluginNext<span class="token punctuation">)</span><span class="token punctuation">;</span>
slider<span class="token punctuation">.</span><span class="token function">start</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>抽象化: 将通用组件模型抽离出来(<code>registerPlugins()</code>,
<code>render</code>)定义成一个Componment类</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">Component</span><span class="token punctuation">&#123;</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">id<span class="token punctuation">,</span> opts <span class="token operator">=</span> <span class="token punctuation">&#123;</span>name<span class="token punctuation">,</span> <span class="token literal-property property">data</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span>id<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>options <span class="token operator">=</span> opts<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>opts<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">registerPlugins</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>plugins</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    plugins<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token parameter">plugin</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> pluginContainer <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">createElement</span><span class="token punctuation">(</span><span class="token string">'div'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      pluginContainer<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>name<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">__plugin</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
      pluginContainer<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> plugin<span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>options<span class="token punctuation">.</span>data<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span>container<span class="token punctuation">.</span><span class="token function">appendChild</span><span class="token punctuation">(</span>pluginContainer<span class="token punctuation">)</span><span class="token punctuation">;</span>
      
      plugin<span class="token punctuation">.</span><span class="token function">action</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">render</span><span class="token punctuation">(</span><span class="token parameter">data</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">/* abstract */</span>
    <span class="token keyword">return</span> <span class="token string">''</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
</ul></li>
<li><p>更多的工作: CSS模板化...</p></li>
</ol>
<h4 id="原则-过程抽象">原则-过程抽象</h4>
<p>我们可以利用JS的动态类型的特性通过过程抽象的思想实现一些处理函数的特殊的函数,
这些函数可以方便的控制函数执行的一些局部细节,
我们一般称这些函数为高阶函数</p>
<p>高阶函数:</p>
<ul>
<li>将函数作为参数</li>
<li>将函数作为返回值</li>
<li>通常用作函数的装饰器</li>
</ul>
<p>高阶函数解决的什么问题</p>
<ul>
<li>为函数的执行设计一些条件</li>
<li>将非纯函数转化为纯函数(纯函数: 无状态的函数,
当输入确定的时候输出就确定了)</li>
</ul>
<p>常见高阶函数举例:</p>
<ul>
<li><p>实现一个<code>once</code>方法, 被他处理过的函数只能执行一次</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">once</span><span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>		<span class="token comment">// 返回处理好的函数</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>fn<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>						<span class="token comment">// 利用闭包保存要处理函数</span>
      <span class="token keyword">const</span> ret <span class="token operator">=</span> <span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>		<span class="token comment">// 执行结果</span>
      fn <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>					<span class="token comment">// 将保存的函数清空</span>
      <span class="token keyword">return</span> ret<span class="token punctuation">;</span>					<span class="token comment">// 返回结果</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>实现一个节流函数(冷却某个时间才能再次触发)</p>
<pre class="language-JS" data-language="JS"><code class="language-JS">function throttle(fn, time &#x3D; 500)&#123;
  let timer;
  return function(...args)&#123;
    if(timer &#x3D;&#x3D; null)&#123;
      fn.apply(this,  args);
      timer &#x3D; setTimeout(() &#x3D;&gt; &#123;
        timer &#x3D; null;
      &#125;, time)
    &#125;
  &#125;
&#125;</code></pre></li>
<li><p>实现一个防抖函数(函数会在调用延时执行,
如果在延时时间内出现二次调用则取消前者执行, 重新计时执行后者)</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">debounce</span><span class="token punctuation">(</span><span class="token parameter">fn<span class="token punctuation">,</span> dur</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  dur <span class="token operator">=</span> dur <span class="token operator">||</span> <span class="token number">100</span><span class="token punctuation">;</span>
  <span class="token keyword">var</span> timer<span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token function">clearTimeout</span><span class="token punctuation">(</span>timer<span class="token punctuation">)</span><span class="token punctuation">;</span>
    timer <span class="token operator">=</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> arguments<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> dur<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>实现一个排队执行函数(可以在任意时间调用函数, 但是不会立即执行,
函数会按顺序执行, 并且固定间隔执行函数,
比如打游戏的时候快速按了100次攻击, 但是角色只会按照固定的速度去攻击)</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">consumer</span><span class="token punctuation">(</span><span class="token parameter">fn<span class="token punctuation">,</span> time</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> tasks <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      timer<span class="token punctuation">;</span>
  
  <span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    tasks<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">bind</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token operator">...</span>args<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span>timer <span class="token operator">==</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
      timer <span class="token operator">=</span> <span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        tasks<span class="token punctuation">.</span><span class="token function">shift</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">call</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">)</span>
        <span class="token keyword">if</span><span class="token punctuation">(</span>tasks<span class="token punctuation">.</span>length <span class="token operator">&lt;=</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
          <span class="token function">clearInterval</span><span class="token punctuation">(</span>timer<span class="token punctuation">)</span><span class="token punctuation">;</span>
          timer <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
        <span class="token punctuation">&#125;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> time<span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>实现一个迭代方法使得我们可以批量操作可迭代对象的元素</p>
<p>例如我们想为数组中的元素执行某个方法我们可以写<code>arr.forEach(d=&gt;foo(d))</code></p>
<p>当我们想为一个可迭代对象实现批量执行时就有点麻烦了,
我们可以实现迭代方法函数</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">iterative</span><span class="token punctuation">(</span><span class="token parameter">fn</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">subject<span class="token punctuation">,</span> <span class="token operator">...</span>rest</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token function">isIterable</span><span class="token punctuation">(</span>subject<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> ret <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
      <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> obj <span class="token keyword">of</span> subject<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        ret<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>obj<span class="token punctuation">,</span> <span class="token operator">...</span>rest<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span>
      <span class="token keyword">return</span> ret<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    <span class="token keyword">return</span> <span class="token function">fn</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> <span class="token punctuation">[</span>subject<span class="token punctuation">,</span> <span class="token operator">...</span>rest<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
</ul>
<h4 id="编程范式">编程范式</h4>
<ul>
<li>命令式: 命令机器<strong>如何去做</strong>事情(how),
这样不管你想要的是什么(what), 它都会按照你的命令实现.
<ul>
<li>过程式: C语言</li>
<li>面向对象式: C++</li>
</ul></li>
<li>声明式: 告诉机器你想要的<strong>是什么</strong>(what),
让机器想出<em>如何</em>去做(how).
<ul>
<li>逻辑式: Prolog</li>
<li>函数式: Ertang</li>
</ul></li>
<li>混合式: 都沾点: JS</li>
</ul>
<p>举例: 想要实现一个属性双态切换</p>
<ul>
<li><p>命令式</p>
<pre class="language-js" data-language="js"><code class="language-js">switcher<span class="token punctuation">.</span><span class="token function-variable function">onclick</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">evt</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">if</span><span class="token punctuation">(</span>evt<span class="token punctuation">.</span>target<span class="token punctuation">.</span>className <span class="token operator">===</span> <span class="token string">'on'</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    evt<span class="token punctuation">.</span>target<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'off'</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token keyword">else</span><span class="token punctuation">&#123;</span>
    evt<span class="token punctuation">.</span>target<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'on'</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>声明式</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">toggle</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>actions</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter"><span class="token operator">...</span>args</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> action <span class="token operator">=</span> actions<span class="token punctuation">.</span><span class="token function">shift</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    actions<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span>action<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token function">action</span><span class="token punctuation">.</span><span class="token function">apply</span><span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">,</span> args<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

switcher<span class="token punctuation">.</span>onclick <span class="token operator">=</span> <span class="token function">toggle</span><span class="token punctuation">(</span>
  <span class="token parameter">evt</span> <span class="token operator">=></span> evt<span class="token punctuation">.</span>target<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'off'</span><span class="token punctuation">,</span>
  <span class="token parameter">evt</span> <span class="token operator">=></span> evt<span class="token punctuation">.</span>target<span class="token punctuation">.</span>className <span class="token operator">=</span> <span class="token string">'on'</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>当我们想把双态切换变为三态, 声明式编程只需要修改</p>
<pre class="language-diff" data-language="diff"><code class="language-diff">function toggle(...actions)&#123;
<span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> return function(...args)&#123;
</span><span class="token prefix unchanged"> </span><span class="token line">   let action = actions.shift();
</span><span class="token prefix unchanged"> </span><span class="token line">   actions.push(action);
</span><span class="token prefix unchanged"> </span><span class="token line">   return action.apply(this, args);
</span><span class="token prefix unchanged"> </span><span class="token line"> &#125;
</span></span>&#125;

switcher.onclick = toggle(
<span class="token inserted-sign inserted"><span class="token prefix inserted">+</span><span class="token line"> evt => evt.target.className = 'warn',
</span></span><span class="token unchanged"><span class="token prefix unchanged"> </span><span class="token line"> evt => evt.target.className = 'off',
</span><span class="token prefix unchanged"> </span><span class="token line"> evt => evt.target.className = 'on'
</span></span>);</code></pre></li>
</ul>
<h4 id="什么是优秀的代码">什么是优秀的代码</h4>
<p>什么是优秀的代码? 风格好? 效率高? 应该在效率要求高的时候尽可能高效,
要求不高的时候尽可能优雅</p>
<p>看一个例子: 如何判断一个3阶矩阵是单位矩阵? 看看人家的代码</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">is_unit3</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token operator">=></span> 
	arr<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span><span class="token operator">!</span>arr<span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span><span class="token operator">!</span>arr<span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span><span class="token operator">!</span>arr<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span>arr<span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span><span class="token operator">!</span>arr<span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span><span class="token operator">!</span>arr<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span><span class="token operator">!</span>arr<span class="token punctuation">[</span><span class="token number">7</span><span class="token punctuation">]</span><span class="token operator">&amp;&amp;</span>arr<span class="token punctuation">[</span><span class="token number">8</span><span class="token punctuation">]</span><span class="token punctuation">;</span></code></pre>
<p>很粗暴, 要是让我写想法是把他二进制化,
然后看看值是不是<code>100010001B</code>, 但是这种方法真的优秀吗?</p>
<p>如果我说这个代码要放在一个图形库的基础函数中使用呢?
没有一个算法有上面代码高效, 毫无疑问, 上面的代码是好代码.</p>
<p>再看一个例子: 我们希望实现一个输出重复字符串的函数</p>
<ul>
<li><p>普通版本</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">repeat</span><span class="token punctuation">(</span><span class="token parameter">str<span class="token punctuation">,</span> len</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span>str <span class="token operator">&amp;&amp;</span> str <span class="token operator">!==</span> <span class="token number">0</span><span class="token punctuation">)</span> str <span class="token operator">=</span> <span class="token string">' '</span><span class="token punctuation">;</span> <span class="token comment">// null&amp;undifined</span>
  <span class="token keyword">let</span> res <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span> i <span class="token operator">&lt;</span> len<span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    res <span class="token operator">+=</span> str<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>非常朴素的<span class="math inline">\(O(n)\)</span>算法</p></li>
<li><p>改进一下: 我们可以利用倍增的思想实现<span
class="math inline">\(O(logN)\)</span>的实现(类似快速幂)</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">repeat</span><span class="token punctuation">(</span>str <span class="token operator">=</span> <span class="token string">' '</span><span class="token punctuation">,</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> res <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">while</span> <span class="token punctuation">(</span>len <span class="token operator">!==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">if</span> <span class="token punctuation">(</span>len <span class="token operator">&amp;</span> <span class="token number">1</span><span class="token punctuation">)</span> res <span class="token operator">+=</span> str<span class="token punctuation">;</span>
    len <span class="token operator">>>>=</span> <span class="token number">1</span><span class="token punctuation">;</span>
    res <span class="token operator">+=</span> res<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token keyword">return</span> res<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>此时执行次数应该是N的二进制位数</p></li>
<li><p>再改进一下: 我们可以优化一下常数实现<span
class="math inline">\(O(logN)\)</span></p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">repeat</span><span class="token punctuation">(</span>str <span class="token operator">=</span> <span class="token string">' '</span><span class="token punctuation">,</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> res <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">do</span> <span class="token punctuation">&#123;</span>
    res <span class="token operator">+=</span> str<span class="token punctuation">;</span>
    str <span class="token operator">+=</span> str<span class="token punctuation">;</span>
    len <span class="token operator">&amp;=</span> len <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span> <span class="token keyword">while</span> <span class="token punctuation">(</span>len<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> res<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>此时执行次数应该是N的二进制中1的个数(但是似乎是错的, 我又改了改,
但是退化到无常数优化的版本)</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">repeat2</span><span class="token punctuation">(</span>str <span class="token operator">=</span> <span class="token string">' '</span><span class="token punctuation">,</span> len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> res <span class="token operator">=</span> <span class="token string">''</span><span class="token punctuation">;</span>
  <span class="token keyword">let</span> i <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
  <span class="token keyword">while</span> <span class="token punctuation">(</span>len<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token punctuation">;</span> <span class="token number">1</span> <span class="token operator">&lt;&lt;</span> i <span class="token operator">&lt;</span> <span class="token punctuation">(</span>len <span class="token operator">&amp;</span> <span class="token operator">-</span>len<span class="token punctuation">)</span><span class="token punctuation">;</span> i<span class="token operator">++</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
      str <span class="token operator">+=</span> str<span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span>
    res <span class="token operator">+=</span> str<span class="token punctuation">;</span>
    len <span class="token operator">&amp;=</span> len <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token keyword">return</span> res<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>优化的是不错, 但是如果我说我的len一般是小于10的呢?
显然第一个版本就是最棒的</p></li>
</ul>
<p>剩下的代码就不一一推演了, 之记录一下我想不到的写法</p>
<ul>
<li><p>判断N是不是4的整数幂</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">isPowerofFour</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">num</span><span class="token punctuation">)</span> <span class="token operator">=></span> 
  num<span class="token operator">></span><span class="token number">0</span> <span class="token operator">&amp;&amp;</span>
  <span class="token punctuation">(</span>num <span class="token operator">&amp;</span> <span class="token punctuation">(</span>num<span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token number">0</span> <span class="token operator">&amp;&amp;</span>
  <span class="token punctuation">(</span>num <span class="token operator">&amp;</span> <span class="token number">0xAAAAAAAA</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token number">0</span></code></pre></li>
<li><p>判断N是不是4的整数幂</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token function-variable function">isPowerofFour</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">num</span><span class="token punctuation">)</span> <span class="token operator">=></span> 
  <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">^1(?:00)*$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">.</span><span class="token function">test</span><span class="token punctuation">(</span>num<span class="token punctuation">.</span><span class="token function">toString</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre></li>
<li><p>实现洗牌算法</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> cards <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">7</span><span class="token punctuation">,</span> <span class="token number">8</span><span class="token punctuation">,</span> <span class="token number">9</span><span class="token punctuation">]</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token operator">*</span> <span class="token function">draw</span><span class="token punctuation">(</span><span class="token parameter">cards</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">const</span> c <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token operator">...</span>cards<span class="token punctuation">]</span><span class="token punctuation">;</span>

  <span class="token keyword">for</span><span class="token punctuation">(</span><span class="token keyword">let</span> i <span class="token operator">=</span> c<span class="token punctuation">.</span>length<span class="token punctuation">;</span> i <span class="token operator">></span> <span class="token number">0</span><span class="token punctuation">;</span> i<span class="token operator">--</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">const</span> pIdx <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>Math<span class="token punctuation">.</span><span class="token function">random</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">*</span> i<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">[</span>c<span class="token punctuation">[</span>pIdx<span class="token punctuation">]</span><span class="token punctuation">,</span> c<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span>c<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span> c<span class="token punctuation">[</span>pIdx<span class="token punctuation">]</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
    <span class="token keyword">yield</span> c<span class="token punctuation">[</span>i <span class="token operator">-</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">draw</span><span class="token punctuation">(</span>cards<span class="token punctuation">)</span><span class="token punctuation">;</span>
console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token operator">...</span>result<span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>复习一下位运算基础</p>
<ul>
<li><p><code>t &amp; (t-1)</code>可以获得一个去除最后一位的数字</p>
<pre class="language-none"><code class="language-none">  1110110000
&amp; 1110101111
------------
  1110100000</code></pre>
<p>相当于去掉了最后一位</p></li>
<li><p><code>t &amp; (-t)</code>或<code>x&amp;(x^(x-1))</code>为<code>lowbit</code>函数</p>
<pre class="language-none"><code class="language-none">  01110110000
&amp; 10001010000
-------------
  00000010000</code></pre></li>
</ul></li>
</ul>
<h3 id="day3-1-web标准与前端开发---李松峰">Day3-1 Web标准与前端开发 -
李松峰</h3>
<p><strong>三个时代</strong></p>
<ul>
<li>只读时代: 单向发布, 链接跳转, 刷新页面</li>
<li>体验时代: Ajax的提出, SPA, 动态交互, jQuery</li>
<li>敏捷时代: React, Vue的出现, 模块化, 组件化</li>
</ul>
<p><strong>前端应用场景</strong></p>
<ul>
<li>浏览器</li>
<li>服务器: node, deno...</li>
<li>命令行: webpack CLI, Vue CLI...</li>
<li>桌面端: Electron, nw.js</li>
<li>移动端: React Native</li>
</ul>
<p><strong>前端语言</strong></p>
<ul>
<li>HTML</li>
<li>CSS</li>
<li>JS</li>
<li>WebAssembly(类汇编化语言, 一般是将C/CPP/Rust代码转化为WASM),
应当注意这一趋势</li>
</ul>
<p><strong>前端学习路线</strong></p>
<p><a target="_blank" rel="noopener" href="https://roadmap.sh/frontend">roadMap</a></p>
<figure>
<img data-src="./frontend-map.png" alt="中文版学习路线" />
<figcaption aria-hidden="true">中文版学习路线</figcaption>
</figure>
<p><strong>浏览器原理</strong></p>
<p><a
target="_blank" rel="noopener" href="https://juejin.cn/post/6844903860612366350">深入理解现代浏览器</a></p>
<p><strong>前端相关组织与标准</strong></p>
<ul>
<li>W3C: XML, HTML, DOM, CSS, WebAPI</li>
<li>ECMA: ECMAScript</li>
<li>WHATWG: HTML5, WebAPI</li>
<li>IETF: TCP/IP, HTTP</li>
</ul>
<h3 id="day3-2-前端调试知识---秃头披风侠">Day3-2 前端调试知识 -
秃头披风侠</h3>
<h4 id="pc端调试chrome-dev-tools">PC端调试(chrome dev-tools)</h4>
<p><strong>Element面板</strong></p>
<p>显示元素的基本结构与样式</p>
<p>Style选项中的过滤器旁边有<code>:hov</code>与<code>.cls</code>按钮,
分别可以为元素设置伪类, 添加新类/应用/取消应用类</p>
<p><strong>查看我们在Elements上修改了哪些东西</strong></p>
<p>切换到Sources-左侧Overides-随便指定个文件夹用于存储修改-之后在Element上的修改就被记录了-在Overrides右侧changes上就可以显示做了哪些修改</p>
<p><strong>Console面板</strong></p>
<p>花式输出日志</p>
<ul>
<li><code>console.log()</code>: 普通的输出</li>
<li><code>console.warn()</code>: 带警告的黄色输出</li>
<li><code>console.error()</code>: 带错误的红色输出</li>
<li><code>console.debug()</code>: 蓝色输出</li>
<li><code>console.info()</code>: 蓝色输出</li>
<li><code>console.table(arr)</code>: 将数组/JSON对象输出为表格</li>
<li><code>console.dir(obj)</code>:
将对象树状输出(对比<code>console.log(body)</code>)</li>
<li><code>console.log('占位符', 对象1, 对象2, ...)</code>:
<ul>
<li><code>%s</code>: 字符串占位符</li>
<li><code>%o</code>: 对象占位符</li>
<li><code>%c</code>: CSS占位符</li>
<li><code>%d</code>: 数字占位符 例如:
<code>console.log('%s %o, %c%s', 'hi', &#123;name: 'tom', age: 18&#125;, 'color: green', 'hello')</code></li>
</ul></li>
<li><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Console">Console对象</a></li>
</ul>
<p><strong>Sources面板</strong></p>
<p>右侧debug工具栏<br />
- Watch: 变量监视 - Breakpoints: 管理断点 - Scope:
查看包含闭包的作用域列表 - Call stack: 调用栈 - XHR/fetch breakpoints:
可以选择在有请求发生的时候设置断点 - DOM breakpoint: 在Element中设置,
达到条件后断开</p>
<p><strong>压缩后代码调试</strong></p>
<p>由于前端代码天生具有开源属性,我们在上线的时候一般会将代码进行压缩,防止自己的代码被别人阅读,但是这也让代码难以调试,
sourcesmap可以帮助我们在浏览器中展示压缩后代码对应的真实代码</p>
<p>sourcemap文件的匹配模式:
在压缩后的文件末尾有<code>//# sourceMappingUrl = demo.js.map</code></p>
<p>sourcemap的工作原理:</p>
<pre class="language-json" data-language="json"><code class="language-json"><span class="token punctuation">&#123;</span>
  <span class="token property">"version"</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>         <span class="token comment">// 版本号</span>
  <span class="token property">"file"</span><span class="token operator">:</span> <span class="token string">"index.js"</span><span class="token punctuation">,</span>   <span class="token comment">// 压缩后文件</span>
  <span class="token property">"sourceRoot"</span><span class="token operator">:</span> <span class="token string">""</span><span class="token punctuation">,</span>     <span class="token comment">// 所有源文件的根路径</span>
  <span class="token property">"sources"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"../src/index.ts"</span><span class="token punctuation">]</span><span class="token punctuation">,</span>     <span class="token comment">// 源文件  </span>
  <span class="token property">"names"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>          <span class="token comment">// 存放转换前的变量名</span>
  <span class="token property">"mappings"</span><span class="token operator">:</span> <span class="token string">";;;AAQA;;GAEG;AACH,IAAM,gBAAgB,GAA2B;IAC/C,EAAE,EAAE;QACF,..., CAAC;AAC3B,CAAC;AAFD,8BAEC"</span><span class="token punctuation">,</span>  <span class="token comment">// 所有映射点</span>
  <span class="token property">"sourcesContent"</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">"/**\n * Locale character mapping ... return str.toLowerCase();\n&#125;\n"</span><span class="token punctuation">]</span>   <span class="token comment">// 所有源文件的内容</span>
<span class="token punctuation">&#125;</span></code></pre>
<p><strong>mappings</strong></p>
<p>mappings 是记录映射关系的核心. 从表面看, mappings 是一个字符串,
里面由很多看似乱码的字符组成. 其实 mappings
是一个数组通过一定的方式编码得到的,
这个数组包含了生成的文件中每行的映射点列表: <pre class="language-js" data-language="js"><code class="language-js">mappings <span class="token operator">=</span> <span class="token punctuation">[</span> 
   第 <span class="token number">1</span> 行的映射点列表<span class="token punctuation">,</span> 
   第 <span class="token number">2</span> 行的映射点列表<span class="token punctuation">,</span> 
   <span class="token operator">...</span> 
<span class="token punctuation">]</span></code></pre>
每行的映射点列表又是一个数组, 包含了该行中所有列的映射点. <pre class="language-js" data-language="js"><code class="language-js">mappings <span class="token operator">=</span> <span class="token punctuation">[</span> 
    <span class="token punctuation">[</span> 第 <span class="token number">1</span> 行第 <span class="token number">1</span> 个映射点<span class="token punctuation">,</span> 第 <span class="token number">1</span> 行第 <span class="token number">2</span> 个映射点<span class="token punctuation">,</span> <span class="token operator">...</span> <span class="token punctuation">]</span> <span class="token comment">// 第 1 行的映射点列表</span>
    <span class="token punctuation">[</span> 第 <span class="token number">2</span> 行第 <span class="token number">1</span> 个映射点<span class="token punctuation">,</span> 第 <span class="token number">2</span> 行第 <span class="token number">2</span> 个映射点<span class="token punctuation">,</span> <span class="token operator">...</span> <span class="token punctuation">]</span> <span class="token comment">// 第 2 行的映射点列表</span>
    <span class="token operator">...</span> 
<span class="token punctuation">]</span></code></pre>
每个映射点又是一个数组, 数组中包含了 5 个数字:
<code>[ 生成文件的列, 源文件索引, 源文件行号, 源文件列号, 名称索引 ]</code>其中,
名称索引可省略. 源文件索引, 源文件行号, 源文件列号也可同时省略,
这表示映射点的数组长度可能是 1, 4 或 5. 源映射所有行列号都是从 0
开始计数的, 本文中所使用的行列号也都是从 0 开始计数的. 举个例子,
比如现在有一个源映射如下: <pre class="language-json" data-language="json"><code class="language-json"><span class="token punctuation">&#123;</span>
  version<span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
  file<span class="token operator">:</span> 'min.js'<span class="token punctuation">,</span>
  names<span class="token operator">:</span> <span class="token punctuation">[</span>'bar'<span class="token punctuation">,</span> 'baz'<span class="token punctuation">,</span> 'n'<span class="token punctuation">]</span><span class="token punctuation">,</span> 
  sourceRoot<span class="token operator">:</span> 'http<span class="token operator">:</span><span class="token comment">//example.com/www/js/',</span>
  sources<span class="token operator">:</span> <span class="token punctuation">[</span>'one.js'<span class="token punctuation">,</span> 'two.js'<span class="token punctuation">]</span><span class="token punctuation">,</span> 
  sourcesContent<span class="token operator">:</span> <span class="token punctuation">[</span>''<span class="token punctuation">,</span> ''<span class="token punctuation">]</span><span class="token punctuation">,</span>
  mappings<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">[</span>
      <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">[</span><span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span>   <span class="token comment">// #13 行</span>
    <span class="token punctuation">]</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre> 以 #13 行数据为例: #13 行出现在
<code>mappings[2]</code> 里面, 因此它表示生成的文件第 2 行的信息. #13
行包含了 5 个数字, 分别表示生成文件的列 = 4, 源文件索引 = 0, 源文件行号
= 3, 源文件列号 = 6, 名称索引 = 0. 最终得到: 生成的文件(即 min.js)中, 行
2 列 4 的位置是从第 0 个源码中行 3 列 6 的位置生成的, 源码中相关的名称是
0(即 bar). 通过多个映射点,
可以一一定义生成的文件中每个位置对应的实际源码位置.</p>
<p>注意即使指定了某一行列的源码位置, 也无法推断相邻行列的源码的位置,
必须一一添加映射.</p>
<p>名称索引可以用于快速定位变量和函数压缩前的名字.</p>
<p><strong>mappings编码</strong></p>
<p>为了节约存储空间, mappings 会被编码成一个字符串.</p>
<ul>
<li>计算相对值:<br />
将映射点中每个数字替换成当前映射点和上一个映射点相应位置的差, 如:
<pre class="language-json" data-language="json"><code class="language-json">mappings<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">[</span>
      <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
      <span class="token punctuation">[</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">6</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">[</span>
      <span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span>
    <span class="token punctuation">]</span>
<span class="token punctuation">]</span></code></pre> 其中第一个映射点不变,
以后每个映射点上每个数字都减去上一个映射点(允许跨行)对应位置的数字(如果映射点元素个数不足
5, 则省略部分按 0 处理), 最后得到: <pre class="language-json" data-language="json"><code class="language-json">mappings<span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">[</span>
      <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">,</span>   <span class="token comment">// 不变</span>
      <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">-1</span><span class="token punctuation">]</span>    <span class="token comment">// 1 = 2 - 1, 0 = 0 - 0, 1 = 3 - 2, 1 = 6 - 5, 1 = 0 - 1</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">[</span>
      <span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">,</span> <span class="token number">-1</span><span class="token punctuation">,</span> <span class="token number">-3</span><span class="token punctuation">,</span> <span class="token number">0</span><span class="token punctuation">]</span>  <span class="token comment">// 3 = 5 - 2,  0 = 0 - 0, -1 = 2 - 3, -3 = 3 - 6, 0 = 0 - 0</span>
    <span class="token punctuation">]</span>
<span class="token punctuation">]</span></code></pre></li>
<li>合并数字<br />
将 mappings 中出现的所有数字写成一行, 不同映射点使用,(逗号)隔开,
不同的行使用;(分号)隔开. <pre class="language-none"><code class="language-none">1 0 2 5 1 , 1 0 1 1 1 ; 3, 0 , -1, -3, 0</code></pre></li>
<li>编码数字 对于每个数字, 都使用 VLQ 编码 将其转为字母, 具体转换方式为:
<ol type="1">
<li>如果数字是负数, 则取其相反数.</li>
<li>将数字转为等效的二进制. 并在末尾补符号位, 如果数字是负数则补 1
否则补 0.</li>
<li>从右往左分割二进制, 一次取 5 位, 不足的补 0.</li>
<li>将分好的二进制进行倒序.</li>
<li>每段二进制前面补 1, 最后一段二进制补 0. 这样每段二进制就是 6 位,
其值范围是 0 到 64(含0, 不含64).</li>
<li>根据 Base64 编码表将每段二进制转为字母</li>
</ol></li>
</ul>
<p>在现在的监控平台中,我们的做法是,将sourcemap与min.js上传到监控平台,监控平台部署到服务器的时候会删除</p>
<p><strong>Performance面板</strong></p>
<p>性能相关</p>
<p><strong>Network</strong></p>
<p>请求相关</p>
<p><strong>Application</strong></p>
<p>存储相关</p>
<h4 id="移动端调试">移动端调试</h4>
<p><strong>代理工具调试(远程调试)</strong></p>
<ul>
<li>charles: 查看控制网络请求(例如将上线网站的某个远程JS代理为本地JS,
将SourcesMap代理到本地)</li>
<li>fiddler</li>
<li>spy-debugger</li>
<li>whistle: 基于Node的跨平台代理调试工具</li>
<li>前端埋点: 在出鼓掌后将日志发送到服务器,
有的时候不方便请求就请求一个图片, url中包含日志,
同时由于图片没有跨域问题, 传输相对方便</li>
</ul>
<h3 id="day4-1-响应式系统与react---牛岳">Day4-1 响应式系统与React -
牛岳</h3>
<p>React应用</p>
<ul>
<li>网页可开发</li>
<li>移动短开发Instagram, Discord</li>
<li>结合Electron进行桌面端开发</li>
<li>3D绘图react-three-fiber</li>
</ul>
<p>React的特性</p>
<ul>
<li>Seamless Client Server Rendering: 可以客户端渲染,
也可以服务端渲染</li>
<li>Reactive: 响应式的,无需手动更新DOM</li>
<li>Performance: 性能</li>
<li>Structural: 组件式的, 使用函数定义</li>
</ul>
<h4 id="react的设计思路">React的设计思路</h4>
<p><strong>原生JS的问题</strong></p>
<ul>
<li>状态更新不更新UI</li>
<li>基本代码层面缺乏封装与隔离, 无组件化</li>
<li>UI与数据之间的依赖关系需要系统维护(造成回调地狱)</li>
</ul>
<p><strong>系统的设计思想</strong></p>
<ul>
<li>转换式系统: 给定输入, 得到输出</li>
<li>响应式系统: 监听事件, 消息驱动. 事件 -&gt; 执行回调 -&gt;
状态变更</li>
</ul>
<p><strong>对React的需求</strong></p>
<ul>
<li>状态更新UI更新</li>
<li>组件化前端代码(最好是语义化的组件): 组件是组件的组合,
组件内部维护状态, 外部不可见, 父组件可以将数据传入组件内部</li>
<li>无需手动维护状态之间的依赖关系, 只需要声明依赖关系</li>
</ul>
<p><strong>状态设计</strong></p>
<ul>
<li>状态传输是单向数据流</li>
<li>状态变化应该更新DOM</li>
<li>公共状态应该由状态管理库管理(否则就要放在最近公共祖先节点(大多数情况下是root))</li>
</ul>
<p><strong>组件设计</strong></p>
<ul>
<li>组件声明了状态与UI的映射</li>
<li>组件是组件与原子组件的自由组合</li>
<li>组件的状态有父组件传入的数据(Props)与组件内部的私有数据(State)</li>
</ul>
<h4 id="react的实现">React的实现</h4>
<p>实现的问题</p>
<ul>
<li>jsx不符合js语法: 语法转意</li>
<li>如何在返回DOM后更新DOM: diff算法, Virtual DOM</li>
<li>State/Props更新的时候会触发渲染函数: diff算法</li>
</ul>
<p><strong>Virtual DOM与diff</strong></p>
<ul>
<li>Virtual DOM是一种与真实DOM同步的JS对象,
可以与DOM建立一一对应的结构</li>
<li>DOM并不是一个JS对象, 为了在JS中操作DOM我们构建了虚拟化DOM,
并使用diff算法更新真实DOM</li>
<li>我们希望diff算法够简单, 还可以尽量减少更新次数</li>
<li>diff实现: 比较Virtual DOM与DOM
<ul>
<li>如果两个节点类型不同: 直接替换子树</li>
<li>如果是同类型的DOM: 只更新</li>
<li>是个是同类型的组件元素: 递归</li>
</ul></li>
</ul>
<h4 id="react状态管理">React状态管理</h4>
<p>将状态抽离到组件外部管理, 方便组件数据管理,
但是会造成组件与管理器强耦合, 降低组件独立性</p>
<p>常见状态库</p>
<ul>
<li>redux: 日薄西山了?</li>
<li>xstat: 基于状态机的状态管理</li>
<li>mobx</li>
<li>rocoil</li>
</ul>
<p>什么样的数据适合放入状态管理库?
这个状态是否是为全局拥有(例如用户头像)</p>
<p><strong>什么是代码聚合性</strong></p>
<p>将频繁相互内部调用的函数放在一起,
使得接口设计时候可以更加"信任"调用者,
减少函数中的各种合法性判断(数据类型等)</p>
<h3 id="day4-2-前端动画实现---蒋翔">Day4-2 前端动画实现 - 蒋翔</h3>
<p>这节课以举例为主涨涨见识</p>
<h4 id="动画基本原理">动画基本原理</h4>
<p>动画: 通过 <strong>快速</strong> <strong>连续排列</strong>
<strong>彼此差异极小</strong>
的连续图像来制造运动<strong>错觉</strong>和变化错觉的过程</p>
<p><strong>前端动画</strong></p>
<ul>
<li>常见动画技术: Sprite动画(快速切换雪碧图), CSS动画, JS动画, SVG动画,
WebGL动画</li>
<li>按照应用分类: UI动画, Web动画, 动画数据可视化</li>
</ul>
<p><strong>需要了解的基本原理</strong></p>
<ul>
<li>计算机图形学基础
<ul>
<li>点线面体场的数学构造方法</li>
<li>几何图形的输入, 存储, 压缩</li>
<li>纹理, 曲线, 光阴的描述算法</li>
<li>物体图形的数据输出(图形接口, 动画技术)硬件与图形交互技术</li>
<li>图形开发软件相关技术</li>
</ul></li>
<li>计算机动画</li>
<li>插值技术: 我们获得了运动的始末态, 需要填补图形运动的中间状态
<ul>
<li>补间动画: 绘制关键帧, 之后计算机补全中间过程(CSS的keyframe,
transition)</li>
<li>逐帧动画: 每一帧都是纯手绘的(Sprite动画)</li>
</ul></li>
</ul>
<p><strong>动画的评价模型</strong></p>
<ul>
<li>帧: 连续变化的多张画面, 每一个画面都是一个帧</li>
<li>帧率: 度量一段时间内的帧数, 单位为FPS</li>
<li>帧率与人眼: 一般10-12FPS动画人可以认为是连贯的,
电脑动画在30FPS以下会感到明显卡顿</li>
</ul>
<h4 id="前端动画分类">前端动画分类</h4>
<p><strong>CSS动画</strong></p>
<p>CSS是一种样式表语言, 用来描述HTML或XML(包括SVG, MathML, XHTML),
CSS动画有三种实现模式</p>
<ol type="1">
<li><p>通过animation相关内容实现精美动画</p>
<ul>
<li><p>使用animation相关API配置动画</p>
<table>
<colgroup>
<col style="width: 17%" />
<col style="width: 11%" />
<col style="width: 17%" />
<col style="width: 35%" />
<col style="width: 17%" />
</colgroup>
<thead>
<tr class="header">
<th>API</th>
<th>值</th>
<th>作用</th>
<th>多值意义</th>
<th>链接</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><code>animation-name</code></td>
<td><code>none|ident</code></td>
<td>指定要应用的动画名字(由<code>@keyfrmaes</code>定义)</td>
<td>指定多个动画, 动画同时执行(<code>,</code>隔开)</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-name">MDN</a></td>
</tr>
<tr class="even">
<td><code>animation-duration</code></td>
<td><code>X s</code>/<code>X ms</code></td>
<td>动画执行时长</td>
<td>与<code>animation-name</code>多值一一对应表示对应动画时长</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-duration">MDN</a></td>
</tr>
<tr class="odd">
<td><code>animation-timing-function</code></td>
<td>缓动关键字/函数(见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/easing-function">MDN</a>)</td>
<td>设置动画的执行节奏</td>
<td>-</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-timing-function">MDN</a></td>
</tr>
<tr class="even">
<td><code>animation-delay</code></td>
<td><code>X s</code>/<code>X ms</code></td>
<td>动画开始延迟</td>
<td>与<code>animation-duration</code>类似</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-delay">MDN</a></td>
</tr>
<tr class="odd">
<td><code>animation-iteration-count</code></td>
<td><code>number</code> / <code>infinite</code></td>
<td>定义动画在结束前运行的次数 <strong>number可以是小数,
例如<code>0.5</code>将播放到动画周期的一半</strong></td>
<td>每次播放动画时, 将使用列表中的下一个值,
在使用最后一个值后循环回第一个值(<strong>与<code>animation-duration</code>不同!</strong>)</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-iteration-count">MDN</a></td>
</tr>
<tr class="even">
<td><code>animation-direction</code></td>
<td><code>normal</code>正常<br /><code>alternate</code>交替正反运行<br /><code>reverse</code>反向运行<br /><code>alternate-reverse</code>
反向运行并交替</td>
<td>播放方向</td>
<td>与<code>animation-duration</code>类似</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-name">MDN</a></td>
</tr>
<tr class="odd">
<td><code>animation-fill-mode</code></td>
<td><code>none</code>:第一个帧<br /><code>forwards</code>:
最后一个帧<br /><code>backwards</code>:
在delay时应用第一个帧<br /><code>both</code>:
<code>forward</code>与<code>backwards</code></td>
<td>动画执行结束后保持DOM在哪个状态</td>
<td>与<code>animation-duration</code>类似</td>
<td><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation-fill-mode">MDN</a></td>
</tr>
<tr class="even">
<td><code>animation-play-state</code></td>
<td><code>running</code></td>
<td><code>paused</code></td>
<td>设置动画状态: 暂停或播放</td>
<td>与<code>animation-duration</code>类似</td>
</tr>
</tbody>
</table></li>
<li><p>使用tramsform移动元素(只能用于盒模型)</p>
<ul>
<li>支持的变化: 平移(<code>translate</code>), 缩放(<code>scale</code>),
旋转(<code>rotate</code>), 倾斜, 定义视距(<code>perspective</code>),
详见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/transform-function">transform-function</a></li>
<li><code>transform-origin</code>定义旋转, 缩放, 倾斜的原点</li>
</ul></li>
<li><p>使用<code>@keyframes name&#123;&#125;</code>定义动画</p></li>
</ul>
<p><strong>举例</strong>: 倒啤酒动画,</p>
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="ZEXdVRQ" data-preview="true" data-user="kairuiliu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<p><span>See the Pen <a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu/pen/ZEXdVRQ">
CSS BEER!</a> by KairuiLiu (<a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu"><span
class="citation" data-cites="kairuiliu">@kairuiliu</span></a>) on
<a target="_blank" rel="noopener" href="https://codepen.io">CodePen</a>.</span></p>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<p>(<code>:actice</code>的时候开始运动)</p></li>
<li><p>使用animation中的stepAPI简单精灵动画</p>
<ul>
<li><code>animation: 0.9s run-h steps(帧数, [start|end])</code></li>
<li>详见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/CSS/animation#step-timing-function">MDN</a></li>
</ul>
<p>举例: <a
target="_blank" rel="noopener" href="https://codepen.io/jiangxiang/pen/GRmarxE">跳舞计算器</a></p></li>
<li><p>使用transition实现简单补间动画</p>
<ul>
<li>使用<code>transition: &lt;prototype&gt; &lt;duration&gt; &lt;timing-function&gt; &lt;delay&gt;</code>定义简单动画</li>
</ul></li>
</ol>
<p>总结</p>
<ul>
<li>优点: 简单高效, 不依赖主线程, 采用GPU加速, 浏览器优化的好</li>
<li>缺点: 不能动态修改与自定义动画内容, 无法实现动画之间的同步</li>
<li>场景: 简单H5页面</li>
<li>推荐库: <a target="_blank" rel="noopener" href="https://animate.style/">animate.css</a>, <a
target="_blank" rel="noopener" href="https://elrumordelaluz.github.io/csshake/">shake.css</a></li>
</ul>
<p><strong>SVG动画</strong></p>
<p>SVG是基于XML的矢量图语言, 可以与CSS, JS很好的配合, 有三种实现方法</p>
<ol type="1">
<li><p>SMIL(同步多媒体集成语言): 在SVG内部通过特殊标签定义动画(用的不多,
兼容性不好, 兼容库: polyfill)</p></li>
<li><p>JS操作SVG:</p>
<ul>
<li><p>常用库: <a target="_blank" rel="noopener" href="http://snapsvg.io/">Snap.svg</a>, <a
target="_blank" rel="noopener" href="https://animejs.com/">anime.js</a></p></li>
<li><p>使用原生Web Animation实现</p></li>
<li><p>举例: 文字溶解</p>
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="BawgMpa" data-preview="true" data-editable="true" data-user="kairuiliu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<p><span>See the Pen <a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu/pen/BawgMpa">
SVG文字变形</a> by KairuiLiu
(<a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu"><span class="citation"
data-cites="kairuiliu">@kairuiliu</span></a>) on
<a target="_blank" rel="noopener" href="https://codepen.io">CodePen</a>.</span></p>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<ul>
<li><p>实现原理就是让第一个字母溶解并透明, 第二个单词反向运动,
两个单词之间其实并没有加入衔接</p></li>
<li><p>溶解实现的原理是: 使用<code>filter</code>的blur让元素便模糊....
但是似乎与直觉不符?
尝试注释掉CSS的第20行<code>filter: url(#threshold);</code>,
这才符合直觉! 这个SVG起到了很大的作用, 他是一个SVG滤镜,
作用是将像素颜色进行二值化(透明度低于阈值的为0, 否则为1)</p></li>
<li><p>实现二值化是借用了SVG中的<code>feColorMatrix</code>,
这个元素的作用是进行颜色变换, 该滤镜基于转换矩阵对颜色进行变换.
每一像素的颜色值(一个表示为[红,绿,蓝,透明度(0-1),1] 的矢量)
都经过矩阵乘法计算出的新颜色. 这是一个4x5的矩阵, 其中第五列是偏置值,
计算方法如下 <span class="math display">\[
\left[
\begin{matrix}
rr&amp;rg&amp;rb&amp;ra&amp;c1\\
gr&amp;gg&amp;gb&amp;ga&amp;c1\\
br&amp;bg&amp;bb&amp;ba&amp;c1\\
ar&amp;ag&amp;ab&amp;aa&amp;c1\\
\end{matrix}
\right]
\times
\left[
\begin{matrix}
r\\g\\b\\a\\1
\end{matrix}
\right]
\]</span> 在这个例子中, 矩阵为 <span class="math display">\[
\left[
\begin{matrix}
1&amp;0&amp;0&amp;0&amp;0\\
0&amp;1&amp;0&amp;0&amp;0\\
0&amp;0&amp;1&amp;0&amp;0\\
0&amp;0&amp;0&amp;255&amp;-140\\
\end{matrix}
\right]
\times
\left[
\begin{matrix}
r\\g\\b\\a\\1
\end{matrix}
\right]
=
\left[
\begin{matrix}
r\\g\\b\\a*255-140
\end{matrix}
\right]
\]</span> 也就是让透明度*255-140, 得到的结果如果&lt;0就被转为0,
如果大于1就被转为1, 实现二值化, 那么如果<code>alpha=140.5/255</code>呢?
我尝试设置了<code>color: rgba(0,0,0,0.550980392)</code>,
结果是直接变为alpha=0, 再想想为什么这里要设置<span
class="math inline">\(aa=255, c4=-140\)</span>呢?
难道是说alpha是有精度的?
也就是rgba表示颜色的时候虽然透明度不像颜色是<span
class="math inline">\(0-255\)</span>而是<span
class="math inline">\(0-1\)</span>, 但是他的精度是<span
class="math inline">\(1/255\)</span>?</p>
<p>设计一个简单的实验验证一下, 只需要将<span
class="math inline">\(aa\)</span>设置为255的因数, 我选取了<span
class="math inline">\(aa=51, offset=-21\)</span>, <span
class="math inline">\(alpha=21.5/51\)</span>, 这样计算得到的应该是<span
class="math inline">\(alpha&#39; \approx 0.5\)</span>,
果然得到了一个半透明的灰色, 老师设置aa=255可以进行二值化的原因就是<span
class="math inline">\(alpha*255\)</span>得到的一定是整数... 回头想想,
如果alpha的精度<span class="math inline">\(&lt;
1/255\)</span>我们也无法将rgba()映射成八位十六进制数表示,
另一个验证方式:
设置设置alpha分别为<code>calc(0.5/255)</code>与<code>calc(0.4/255)</code>,
查看计算样式值</p></li>
</ul></li>
<li><p>举例: SVG写字动画</p>
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="yLzdrKy" data-preview="true" data-user="kairuiliu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<p><span>See the Pen <a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu/pen/yLzdrKy">
SVG 写字动画</a> by KairuiLiu
(<a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu"><span class="citation"
data-cites="kairuiliu">@kairuiliu</span></a>) on
<a target="_blank" rel="noopener" href="https://codepen.io">CodePen</a>.</span></p>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<ul>
<li><p>SVG中<code>line</code>标签的<code>stroke-dasharray</code>属性控制用来描边的<strong>点划线</strong>的图案范式他的值是一个<code>&lt;length&gt;</code>和<code>&lt;percentage&gt;</code>数列,
数与数之间用逗号或者空白隔开, 指定短划线和缺口的长度.
如果提供了奇数个值, 则这个值的数列重复一次, 从而变成偶数个值. 因此,
5,3,2等同于5,3,2,5,3,2. , 例如以下表示</p>
<p class="codepen" data-height="300" data-default-tab="result" data-slug-hash="XWeLQEK" data-preview="true" data-user="kairuiliu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<p><span>See the Pen <a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu/pen/XWeLQEK">
stroke-dasharray&amp;stroke-dashoffset</a> by KairuiLiu
(<a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu"><span class="citation"
data-cites="kairuiliu">@kairuiliu</span></a>) on
<a target="_blank" rel="noopener" href="https://codepen.io">CodePen</a>.</span></p>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script></li>
<li><p>SVG中<code>line</code>标签的<code>stroke-dashoffset</code>属性指定了dash模式到路径开始的距离(也就是这条线的第一个像素是<code>stroke-dasharray</code>的第几个像素,
例如)</p>
<pre class="language-svg" data-language="svg"><code class="language-svg"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>line</span> <span class="token attr-name">stroke-dasharray</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>5, 1<span class="token punctuation">"</span></span> <span class="token attr-name">x1</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token attr-name">y1</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token attr-name">x2</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>24<span class="token punctuation">"</span></span> <span class="token attr-name">y2</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>10<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span></code></pre>
<p>的效果是<code>-----+-----+-----+-----+</code></p>
<p>设置<code>stroke-dashoffset: 3</code></p>
<p>的效果是<code>--+-----+-----+-----+---</code>(<code>+</code>表示空白)</p>
<p>看起来就是将纹理反向移动了3</p>
<p>可以利用这个属性做一个蚂蚁线运动动画</p>
<p class="codepen" data-height="300" data-default-tab="css,result" data-slug-hash="KKXjYoP" data-preview="true" data-user="kairuiliu" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
<p><span>See the Pen <a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu/pen/KKXjYoP">
SVG 使用stroke-dashoffset和stroke-dashoffset实现笔画效果</a> by
KairuiLiu (<a target="_blank" rel="noopener" href="https://codepen.io/kairuiliu"><span class="citation"
data-cites="kairuiliu">@kairuiliu</span></a>) on
<a target="_blank" rel="noopener" href="https://codepen.io">CodePen</a>.</span></p>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>
<p>很容易理解,
我们就是想变化<code>stroke-dashoffset</code>实现类似蚂蚁线运动的效果,
还有一个小问题, <code>stroke-dashoffset</code>的最大值是怎么算出来的呢?
使用<code>path.getTotalLength()</code>获取path长度(还可以使用<code>path.getPointAtLength()</code>获取曲线上某个长度对应的坐标点)见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/SVGGeometryElement/getTotalLength">MDN</a>与<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/SVGGeometryElement/getPointAtLength">MDN</a></p></li>
<li><p>有了上面这两个东西我们就很好做了,
只需要设置<code>stroke-dashoffset</code>为0-&gt;length即可</p></li>
</ul></li>
</ul>
<p>总结</p>
<ul>
<li>优点: 效果炫酷, 清晰度高</li>
<li>缺点: 实现复杂, 有性能问题</li>
</ul></li>
<li><p>CSS动画: 使用CSS操作SVG元素</p></li>
</ol>
<p><strong>JS动画</strong></p>
<p>封装一个JS函数,
指定间隔的时候计算播放进度并手动调整animation的播放状态,
方便对元素进行大量动画控制</p>
<p><strong>对比</strong></p>
<table>
<colgroup>
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
<col style="width: 25%" />
</colgroup>
<thead>
<tr class="header">
<th>类型</th>
<th>优点</th>
<th>缺点</th>
<th>场景</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>CSS</td>
<td>浏览器有优化, 性能好, 实现简单</td>
<td>不够灵活, 兼容性不好, 复杂动画不好实现</td>
<td>简单的</td>
</tr>
<tr class="even">
<td>JS</td>
<td>灵活, 粒度大, 可以封装复杂缓动函数, 多状态控制</td>
<td>调试难, 优雅降级, 复杂度高</td>
<td>复杂的</td>
</tr>
<tr class="odd">
<td>SVG</td>
<td>炫酷动画</td>
<td>性能要求大, 实现复杂</td>
<td>特定场景(滤镜, 溶解, 模糊)</td>
</tr>
</tbody>
</table>
<h4 id="实现前端js动画">实现前端JS动画</h4>
<p>封装一个简单的动画函数</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">/**
 *
 * @param &#123;function&#125; easing 缓动函数, 线性时间到进度的映射
 * @param &#123;function&#125; draw 根据动画进度绘图函数
 * @param &#123;function&#125; duration 动画持续时间
 */</span>

<span class="token keyword">function</span> <span class="token function">animation</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">&#123;</span> easing<span class="token punctuation">,</span> draw<span class="token punctuation">,</span> duration <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> start <span class="token operator">=</span> performance<span class="token punctuation">.</span><span class="token function">now</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>						<span class="token comment">// 1</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token function">requestAnimationFrame</span><span class="token punctuation">(</span><span class="token keyword">function</span> <span class="token function">animate</span><span class="token punctuation">(</span><span class="token parameter">time</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>		<span class="token comment">// 2</span>
      <span class="token keyword">const</span> timeFraction <span class="token operator">=</span> <span class="token punctuation">(</span>time <span class="token operator">-</span> start<span class="token punctuation">)</span> <span class="token operator">/</span> duration<span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>timeFraction <span class="token operator">></span> <span class="token number">1</span><span class="token punctuation">)</span> timeFraction <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>
      <span class="token keyword">const</span> progress <span class="token operator">=</span> <span class="token function">easing</span><span class="token punctuation">(</span>timeFraction<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token function">draw</span><span class="token punctuation">(</span>progress<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">if</span> <span class="token punctuation">(</span>timeFraction <span class="token operator">&lt;</span> <span class="token number">1</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
        <span class="token function">requestAnimationFrame</span><span class="token punctuation">(</span>animate<span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span> <span class="token keyword">else</span> <span class="token punctuation">&#123;</span>
        <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> <span class="token function-variable function">draw</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">process</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  ele<span class="token punctuation">.</span>style<span class="token punctuation">.</span>tranform <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">translate(</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>progress <span class="token operator">*</span> <span class="token number">1000</span><span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">px,0)</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">easing</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">timeFraction</span><span class="token punctuation">)</span> <span class="token operator">=></span> timeFraction <span class="token operator">**</span> <span class="token number">2</span><span class="token punctuation">;</span>

<span class="token function">animation</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span> easing<span class="token punctuation">,</span> draw<span class="token punctuation">,</span> <span class="token literal-property property">duration</span><span class="token operator">:</span> <span class="token number">1000</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>注意:</p>
<ul>
<li>1处似乎是想要获取一个当前时间,
但是使用的不是<code>Date.now()</code>,
原因是<code>performance.now()</code>可以精确到微秒级别,
同时在移动端设备上<code>Date.now()</code>是很容易被篡改的</li>
<li>2处似乎是想要设置一个很短时间定时器, 进行动画刷新,
但是不使用<code>setInterval</code>,
<code>requestAnimationFrame</code>是一个钩子函数,
在<strong>浏览器准备重绘</strong>的时候执行, 这样可以保证
<ul>
<li>不会丢帧 (浏览器重绘的周期是不确定的(只知道很快, 可能取决于屏幕帧率,
见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame">MDN</a>),
当浏览器重绘的时候定时器可能还没到),</li>
<li>页面在后台的时候动画不会执行, 减少资源消耗</li>
</ul></li>
</ul>
<p><strong>关于贝塞尔曲线</strong></p>
<ul>
<li><p>解决的问题: 如何在计算机中表示一个曲线</p></li>
<li><p>原理:</p>
<ul>
<li>二次贝塞尔曲线: 按顺序定义两个点<span
class="math inline">\(P_1\)</span>, <span
class="math inline">\(P_2\)</span>, 定义一个新点<span
class="math inline">\(P\)</span>, 取<span class="math inline">\(t\in
[0,1]\)</span>, 在<span class="math inline">\(t=t_0\)</span>时, <span
class="math inline">\(P\)</span>的位置是线段<span
class="math inline">\(P_1P_2\)</span>上距离<span
class="math inline">\(P_1\)</span>长度为<span class="math inline">\(t
\times length_{P_1P_2}\)</span>的位置</li>
<li>二次贝塞尔曲线: 按顺序定义三个点<span
class="math inline">\(P_1\)</span>, <span
class="math inline">\(P_2\)</span>, <span
class="math inline">\(P_3\)</span>, 定义三个新点<span
class="math inline">\(P_4\)</span>, <span
class="math inline">\(P_5\)</span>, <span
class="math inline">\(P\)</span>, 取<span class="math inline">\(t\in
[0,1]\)</span>, 在<span class="math inline">\(t=t_0\)</span>时, <span
class="math inline">\(P_4\)</span>的位置是线段<span
class="math inline">\(P_1P_2\)</span>上距离<span
class="math inline">\(P_1\)</span>长度为<span class="math inline">\(t
\times length_{P_1P_2}\)</span>的位置, <span
class="math inline">\(P_5\)</span>的位置是线段<span
class="math inline">\(P_2P_3\)</span>上距离<span
class="math inline">\(P_2\)</span>长度为<span class="math inline">\(t
\times length_{P_2P_4}\)</span>的位置, 连接<span
class="math inline">\(P_4P_5\)</span>, <span
class="math inline">\(P\)</span>在线段<span
class="math inline">\(P_4P_5\)</span>上距离<span
class="math inline">\(P_4\)</span>长度为<span class="math inline">\(t
\times length_{P_4P_5}\)</span>的位置, <span
class="math inline">\(P\)</span>的轨迹就是二次贝塞尔曲线</li>
<li>以此类推, 三次贝塞尔曲线就是取三个线段上三个点, 连成两个线段,
取二次贝塞尔曲线在<span class="math inline">\(t\)</span>时的位置, 见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/en-US/docs/Glossary/B%C3%A9zier_curve">MDN</a></li>
</ul>
<p>在线演示: <a
target="_blank" rel="noopener" href="https://cubic-bezier.com/">cubic-bezier</a></p></li>
<li><p>如何实现贝塞尔曲线: 常用的就是三次贝塞尔曲线, 我们有锚点<span
class="math inline">\(P_1, P_2, P_3, P_4\)</span>, 其中固定<span
class="math inline">\(P_1=(0,0), P_4=(1,1)\)</span>在, 变量只有<span
class="math inline">\(P_{2}, P_{3}\)</span>, 曲线公式为 <span
class="math display">\[
B(t) = P_1(1-t^3)+3P_2t(1-t)^2+3P_3t^2(1-t)+P_4t^3, t\in [0,1]
\]</span></p></li>
</ul>
<h4 id="实践">实践</h4>
<p><strong>常见库</strong></p>
<ul>
<li>SVG动画:
<ul>
<li><a target="_blank" rel="noopener" href="http://snapsvg.io/">Snap.svg</a>: 现代SVG图形库</li>
<li><a target="_blank" rel="noopener" href="https://svgjs.dev/docs/3.0/">Svg.js</a>:
用于SVG操作与动画</li>
</ul></li>
<li>JS动画:
<ul>
<li><a target="_blank" rel="noopener" href="https://greensock.com/gsap/">GSAP</a>: JS动画库</li>
<li><a target="_blank" rel="noopener" href="http://tweenjs.github.io/tween.js/">TweenJS</a>:
强大的补间/动画库</li>
<li><a target="_blank" rel="noopener" href="https://velocity.apache.org/">Velocity</a>:
加速的JS动画</li>
</ul></li>
<li>CSS动画
<ul>
<li><a target="_blank" rel="noopener" href="https://animate.style/">Animate.css</a>: 没得说</li>
</ul></li>
</ul>
<p><strong>工作流程</strong></p>
<pre class="mermaid">graph LR
动画帧 --> 代码与设计文件 --> 代码</pre>
<p>建议用封装好的动画库, 实在需要自己实现推荐精灵图,
或者使用lottie格式文件(是一种指令化的格式, 可以在AE中直接导出,
只需要在JS中引入文件即可)</p>
<p><strong>动画优化</strong></p>
<p>JS是单线程的, 我们需要从减少计算的角度进行优化</p>
<ul>
<li><p>性能角度</p>
<p>页面渲染的一般步骤为</p>
<pre class="mermaid">  graph LR
JS --> CSS与计算样式 --> 重排布局 --> 绘制 --> 渲染合并</pre>
<p>最占时间的是重排与绘制,
我们希望在<code>requestAnimationFrame</code>的时候尽量避免这两步,
也就是说我们希望我们使用<code>@keyframe</code>中的CSS属性尽量不需要这两不就可以实现(例如不要设置<code>display</code>从<code>none</code>到其他值(必然会重排),
用<code>translate</code>代替<code>top/left/right/bottom</code>,
用<code>scale</code>代替<code>width/height</code>,
<code>opacity</code>代替<code>diaplay/visibility</code>),
具体那些属性的更新不涉及到这两步见: <a
target="_blank" rel="noopener" href="https://csstriggers.com/">csstriggers</a></p></li>
<li><p>算法角度</p>
<ul>
<li>使用线性函数代替真实计算</li>
<li>几何模型优化</li>
<li>碰撞检测优化</li>
</ul></li>
<li><p>内存缓存youhua</p></li>
<li><p>离屏绘制(<code>requestAnimationFrame</code>)</p></li>
</ul>
<h3 id="day5-1-http实用指南---杨超男">Day5-1 HTTP实用指南 - 杨超男</h3>
<p>梦回计算机网络~</p>
<h4 id="概述">概述</h4>
<p>HTTP(HyperText Transfer Protocol, 超文本传输协议)</p>
<ul>
<li>应用层协议, 基于TCP</li>
<li>无状态的请求响应模式</li>
<li>简单可扩展(在<code>header</code>,
<code>content</code>中插入信息)</li>
</ul>
<h4 id="协议分析">协议分析</h4>
<p><strong>发展历程</strong></p>
<ul>
<li><p><code>HTTP/0.9</code>: 单行协议</p>
<p>支持GET请求, 只能响应HTML文件</p></li>
<li><p><code>HTTP/1.0</code>: 构建扩展性</p>
<p>增加Header, 增加状态码, 支持多文档类型...</p></li>
<li><p><code>HTTP/1.1</code>: 标准化协议</p>
<p>链接复用, 缓存, 内容协商</p></li>
<li><p><code>HTTP/2</code>: 更优异的表现</p>
<p>二进制协议, 压缩header, 服务器推送</p></li>
<li><p><code>HTTP/3</code>: 草案阶段</p></li>
</ul>
<p><strong>报文结构</strong></p>
<ul>
<li><p><code>Http/1.1</code></p>
<ul>
<li><p>start-line:</p>
<p>请求: <code>方法(POST/GET) HTTP/1.1</code></p>
<p>响应: <code>HTTP/1.1 状态码 状态解释</code></p></li>
<li><p>http headers</p></li>
<li><p>empty line</p></li>
<li><p>body</p></li>
</ul></li>
<li><p><code>Http/2</code></p>
<ul>
<li><p>兼容http1.1结构</p></li>
<li><p>抛弃ASCII编码采用二进制编码</p></li>
<li><p>引入帧与流的概念:</p>
<ul>
<li><p>帧(frame)</p>
<p>帧: 是<code>HTTP2.0</code> 中数据传输的最小单位. 因此帧不仅要细分表达
<code>HTTP1.x</code> 中的各个部分, 也优化了 <code>HTTP1.x</code>
表达不好的地方, 同时还增加了 <code>HTTP1.x</code> 表达不了的方式.</p>
<p>每一帧都包含几个字段: <code>length</code>, <code>type</code>,
<code>flags</code>, <code>stream identifier</code>,
<code>frame playload</code>等等.</p>
<p>其中 type 代表帧的类型, 在 HTTP2 的标准中定义了 10 种类型.</p>
<ol type="1">
<li>HEADERS frame</li>
<li>DATA frame</li>
<li>PRIORITY (设置流的优先级)</li>
<li>RST_STREAM (终止流)</li>
<li>SETTINGs (设置此连接的参数)</li>
<li>PUSH_PROMISE (服务器推送)</li>
<li>PING (测量RTT)</li>
<li>GOAWAY (终止连接)</li>
<li>WINDOW_UPDATE (流量控制)</li>
<li>CONTINUATION (继续传输头部数据)</li>
</ol>
<p>在 HTTP2.0 中, 它把数据包的两大部分分成了 <code>header frame</code>
和 <code>data frame</code>, 也就是 头部帧 和 数据体帧.</p></li>
<li><p>流(stream)</p>
<p>流: 存在于连接中的一个虚拟通道. 流可以承载双向消息,
每个流都有一个唯一的整数 ID.</p>
<p><code>HTTP2.0</code> 长连接中的数据是不按请求响应顺序发送的,
一个完整的请求或响应可能会分成非连续多次发送, 有以下几个特点:</p>
<ul>
<li>双向性: 同一个流内, 可以同时发送和接收数据</li>
<li>有序性: 流中被传输的数据就是二进制帧.
帧在流上的被发送与被接收都是按照顺序进行的</li>
<li>并行性: 流中的二进制帧都是被并行传输的, 无需按照顺序等待</li>
<li>流的创建: 流可以被客户端或服务器单方面建立, 使用或共享</li>
<li>流的关闭: 流也可以被任意一方关闭</li>
<li>HEADERS 帧在 DATA 帧前面</li>
<li>流的 ID 都是奇数, 说明是由客户端发起的, 这是标准规定的,
那么服务端发起的就是偶数啦</li>
</ul></li>
</ul></li>
<li><p>链接都是永久的, 也就是支持多路复用技术, 也就是连接上以后不断开,
支持多次连接</p></li>
<li><p>浏览器可以拒绝服务器大量数据推送</p></li>
<li><p>服务器可以主动推送</p></li>
</ul></li>
</ul>
<p><strong>Http请求方法</strong></p>
<table>
<colgroup>
<col style="width: 8%" />
<col style="width: 75%" />
<col style="width: 7%" />
<col style="width: 7%" />
</colgroup>
<thead>
<tr class="header">
<th>方法</th>
<th>解释</th>
<th>安全的</th>
<th>幂等的</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>GET</td>
<td>请求一个指定资源的表示形式,
使用GET的请求应该只被用于<strong>获取数据</strong></td>
<td>✔️</td>
<td>✔️</td>
</tr>
<tr class="even">
<td>HEAD</td>
<td>请求一个与GET请求的响应相同的响应,
但<strong>没有响应体</strong>(开发者不常用,
浏览器可能用(判断资源过期))</td>
<td>✔️</td>
<td>✔️</td>
</tr>
<tr class="odd">
<td>POST</td>
<td>用于将<strong>实体提交</strong>到指定的资源,
通常导致在服务器上的状态变化或副作用</td>
<td></td>
<td></td>
</tr>
<tr class="even">
<td>PUT</td>
<td>用请求有效<strong>载荷替换</strong>目标资源的所有当前表示</td>
<td></td>
<td>✔️</td>
</tr>
<tr class="odd">
<td>DELETE</td>
<td><strong>删除</strong>指定的资源</td>
<td></td>
<td>✔️</td>
</tr>
<tr class="even">
<td>CONNECT</td>
<td>建立一个到由目标资源标识的服务器的隧道(开发者不常用,
浏览器可能用(建立连接过程))</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>OPTIONS</td>
<td>用于<strong>描述目标资源</strong>的通信选项(作为传输之前的前置请求)</td>
<td>✔️</td>
<td>✔️</td>
</tr>
<tr class="even">
<td>TRACE</td>
<td>沿着到目标资源的路径执行一个消息环回<strong>测试</strong>(用得少)</td>
<td></td>
<td></td>
</tr>
<tr class="odd">
<td>PATCH</td>
<td>用于对资源应用<strong>部分修改</strong>(用得少)</td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<ul>
<li>安全的: 不修改服务器数据</li>
<li>幂等的: 多次请求与一次请求一样</li>
</ul>
<p><strong>常见状态码</strong></p>
<ul>
<li>1xx: 成功接收请求, 正在处理</li>
<li>2xx: 成功接收请求, 理解, 处理
<ul>
<li>200: 请求成功</li>
</ul></li>
<li>3xx: 重定向, 需要继续请求
<ul>
<li>301: 被请求的资源已永久移动到新位置</li>
<li>302: 请求的资源现在临时从不同的 URI 响应请求</li>
</ul></li>
<li>4xx: 客户端错误, 请求语法错误或无法实现
<ul>
<li>401: 当前请求需要用户验证</li>
<li>404: 请求失败, 请求所希望得到的资源未被在服务器上发现</li>
</ul></li>
<li>5xx: 服务端错误, 服务端实现失败
<ul>
<li>500: 服务器遇到了不知道如何处理的情况.</li>
<li>504: 当服务器作为网关, 不能及时得到响应时返回此错误代码.</li>
</ul></li>
</ul>
<p>详见<a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/web/http/status">MDN</a></p>
<p><strong>RESTful API</strong>: 一种API设计风格(下面是从<a
target="_blank" rel="noopener" href="https://restfulapi.cn/">中文站</a>上抄来的)</p>
<ul>
<li><p>目的</p>
<ul>
<li><p>充分的利用 HTTP 协议的各种功能, 是 HTTP 协议的最佳实践</p></li>
<li><p>让软件更加清晰, 更简洁, 更有层次, 可维护性更好</p></li>
</ul></li>
<li><p>请求设计(请求 = 动词 + 宾语)</p>
<ul>
<li><p>动词 使用五种 HTTP 方法, 对应 CRUD 操作.</p></li>
<li><p>宾语 URL 应该全部使用名词复数, 可以有例外,
比如搜索可以使用更加直观的 search .</p></li>
<li><p>过滤信息（Filtering） 如果记录数量很多, API应该提供参数,
过滤返回结果. ?limit=10 指定返回记录的数量 ?offset=10
指定返回记录的开始位置.</p></li>
</ul></li>
<li><p>API 响应设计</p>
<ul>
<li>使用 HTTP 的状态码: 客户端的每一次请求, 服务器都必须给出回应.
回应包括 HTTP 状态码和数据两部分. 五大类状态码, 总共100多种,
覆盖了绝大部分可能遇到的情况. 每一种状态码都有约定的解释,
客户端只需查看状态码, 就可以判断出发生了什么情况. API
不需要1xx状态码.</li>
<li>服务器回应数据
<ul>
<li>客户端请求时, 要明确告诉服务器, 接受 JSON 格式, 请求的 HTTP 头的
ACCEPT 属性要设成 application/json</li>
<li>服务端返回的数据, 不应该是纯文本, 而应该是一个 JSON 对象.
服务器回应的 HTTP 头的 Content-Type 属性要设为 application/json</li>
<li>错误处理 如果状态码是4xx, 就应该向用户返回出错信息. 一般来说,
返回的信息中将 error 作为键名, 出错信息作为键值即可. {error: "Invalid
API key"}</li>
<li>认证 RESTful API 应该是无状态, 每个请求应该带有一些认证凭证.
推荐使用 JWT 认证, 并且使用 SSL</li>
<li>Hypermedia 即返回结果中提供链接, 连向其他API方法, 使得用户不查文档,
也知道下一步应该做什么</li>
</ul></li>
</ul></li>
<li><p>举例: 设计一个动物园</p>
<table>
<thead>
<tr class="header">
<th>请求</th>
<th>语义</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>GET/zoos</td>
<td>列出所有动物园</td>
</tr>
<tr class="even">
<td>POST/zoos</td>
<td>新建一个动物园</td>
</tr>
<tr class="odd">
<td>GET/zoos/:id</td>
<td>获取某个指定动物园的信息</td>
</tr>
<tr class="even">
<td>PUT/zoos/:id</td>
<td>更新某个指定动物园的全部信息</td>
</tr>
<tr class="odd">
<td>PATCH/zoos/:id</td>
<td>更新某个指定动物园的部分信息</td>
</tr>
<tr class="even">
<td>DELETE/zoos/:id</td>
<td>删除某个动物园</td>
</tr>
<tr class="odd">
<td>GET/zoos/:id/animals</td>
<td>列出某个指定动物园的所有动物</td>
</tr>
<tr class="even">
<td>DELETE/zoos/:id/animals/:id</td>
<td>删除某个指定动物园的指定动物</td>
</tr>
</tbody>
</table></li>
</ul>
<p><strong>常见请求头</strong></p>
<table>
<colgroup>
<col style="width: 22%" />
<col style="width: 77%" />
</colgroup>
<thead>
<tr class="header">
<th>请求头</th>
<th>意义</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Content-Type</td>
<td>请求的与实体对应的MIME信息</td>
</tr>
<tr class="even">
<td>Cache-Control</td>
<td>指定请求和响应遵循的缓存机制</td>
</tr>
<tr class="odd">
<td>If-Modified-Since</td>
<td>如果请求的部分在指定时间之后被修改则请求成功,
未被修改则返回304代码</td>
</tr>
<tr class="even">
<td>Expires</td>
<td>请求的特定的服务器行为(相对于文件最后访问时间或绝对修改时间)</td>
</tr>
<tr class="odd">
<td>Max-age</td>
<td>缓存有效期(相对请求时间)</td>
</tr>
<tr class="even">
<td>If-None-Match</td>
<td>如果内容未改变返回304代码</td>
</tr>
<tr class="odd">
<td>Cookie</td>
<td>HTTP请求发送时,
会把保存在该请求<strong>同域</strong>下的所有cookie值一起发送给web服务器.</td>
</tr>
<tr class="even">
<td>Referer</td>
<td>先前网页的地址, 当前请求网页紧随其后,即来路</td>
</tr>
<tr class="odd">
<td>Origin</td>
<td>请求最初发起人(精确到端口)</td>
</tr>
<tr class="even">
<td>User-Agent</td>
<td>User-Agent的内容包含发出请求的用户信息</td>
</tr>
</tbody>
</table>
<p><strong>常见响应头</strong></p>
<table>
<colgroup>
<col style="width: 31%" />
<col style="width: 68%" />
</colgroup>
<thead>
<tr class="header">
<th>响应头</th>
<th>意义</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Content-Type</td>
<td>服务端返回的实体内容的类型</td>
</tr>
<tr class="even">
<td>Cache-Control</td>
<td>指定请求和响应遵循的缓存机制, 如no-cache</td>
</tr>
<tr class="odd">
<td>Last-Modified</td>
<td>请求资源的最后修改时间</td>
</tr>
<tr class="even">
<td>Expires</td>
<td>应该在什么时候认为文档已经过期,从而不再缓存它</td>
</tr>
<tr class="odd">
<td>Max-age</td>
<td>客户端的本地资源应该缓存多少秒, 开启了Cache-Control后有效</td>
</tr>
<tr class="even">
<td>ETag</td>
<td>资源的特定版本的标识符, Etags类似于指纹</td>
</tr>
<tr class="odd">
<td>Set-Cookie</td>
<td>设置和页面关联的cookie, 服务器通过这个头部把cookie传给客户端</td>
</tr>
<tr class="even">
<td>Server</td>
<td>服务器的一些相关信息</td>
</tr>
<tr class="odd">
<td>Access-Control-Allow-Origin</td>
<td>服务器遄允许的请求Oriain头部（譬如为*)</td>
</tr>
</tbody>
</table>
<p><strong>缓存相关知识</strong></p>
<ul>
<li><p>强缓存: 只要文件没有过期我就用</p>
<ul>
<li>Expire头: 时间戳</li>
<li>Cache-Control头
<ul>
<li>可缓存性: no-cache(协商缓存), no-store(不使用缓存)</li>
<li>到期: max-age</li>
<li>过期重新加载: must-revalidate(一旦过期必须重新请求,
例如脱机后缓存过期如果没有这个属性我们还是可以用的)</li>
</ul></li>
</ul></li>
<li><p>协商缓存: 用不用缓存需要与服务器沟通决定</p>
<ul>
<li>Etag头: 文件版本标识, 类似于电子指纹</li>
<li>Last-Modified头: 最后修改时间</li>
</ul></li>
<li><p>浏览器请求流程</p>
<pre class="mermaid">  graph TB
发起请求,检查缓存 --> 缓存为强缓存且新鲜这使用 --Y--> 读取浏览器缓存 --> 返回结果
缓存为强缓存且新鲜这使用 --N--> 检查上一次缓存ETag --有ETag--> 发起if-None-Match请求 --> 获取结果
检查上一次缓存ETag --无ETag--> 获取缓存的Last-Modified --> 发起if-Modified-Since --> 获取结果
获取结果 --304-->  读取浏览器缓存
获取结果 --200--> 收取最新文件并缓存 --> 返回结果</pre>
<p>ETag与Last-Modified的作用类似, 但是由于客户端与服务器时间可能不一样,
所以优先使用Etag</p></li>
</ul>
<p><strong>Cookie</strong></p>
<table>
<colgroup>
<col style="width: 30%" />
<col style="width: 69%" />
</colgroup>
<thead>
<tr class="header">
<th>字段</th>
<th>意义</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>Name=value</td>
<td>各种cookie的名称和值</td>
</tr>
<tr class="even">
<td>Expires=Date</td>
<td>Cookie的有效期,缺省时Cookie仅在浏览器关闭之前有效</td>
</tr>
<tr class="odd">
<td>Path=Path</td>
<td>限制指定Cookie的发送范围的文件目录, 默认为当前</td>
</tr>
<tr class="even">
<td>Domain=domain</td>
<td>限制cookie生效的域名, 默认为创建cookie的服务域名</td>
</tr>
<tr class="odd">
<td>secure</td>
<td>仅在HTTPS安全连接时, 才可以发送Cookie</td>
</tr>
<tr class="even">
<td>HttpOnly</td>
<td>JavaScript 脚本无法获得Cookie</td>
</tr>
<tr class="odd">
<td>SameSite=[None/Strict/Lax]</td>
<td>- 同站, 跨站请求都可发送<br />- Strict 仅在同站发送<br />-
允许与顶级导航一起发送,并将与第三方网站发起的GET请求一起发送</td>
</tr>
</tbody>
</table>
<h4 id="常见场景的应用">常见场景的应用</h4>
<ul>
<li><p><strong>静态资源方案</strong>:
缓存+CDN+文件名hash(防止缓存期内无法更新)</p></li>
<li><p><strong>登录方案</strong>:</p>
<ol type="1">
<li><p>跨域请求:
先发起<code>OPTION</code>请求询问服务器是否允许跨域请求,
若允许则发起正式请求</p></li>
<li><p>跨域解决方案: CORS, 代理服务器, iframe</p></li>
<li><p>登录状态保存</p>
<ul>
<li>Session+cookie: 登录成功之后服务器返回cookie</li>
<li>JWT</li>
</ul>
<p>session和cookie成一套体系, session依赖于cookie,
session和cookie都容易被csrf攻击,
而且session类型的状态保持只能用于浏览器中的, 对于用户的登录和登出,
使用session会更灵活一些. jwt是json数据适用于各种语言,
跨语言请求非常方便, jwt可以存在于各种客户端, 不仅仅是浏览器, 扩展性更强,
对数据进行加密, 数据非常安全.</p></li>
</ol></li>
<li><p><strong>预加载与预解析</strong>: <a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/HTML/Element/link#attr-as">HTML的rel属性与as属性</a></p></li>
</ul>
<h4 id="更多的协议">更多的协议</h4>
<ul>
<li>聊天室: 高实时性, 双向同行, 可以考虑ws, wss</li>
<li>QUIC(Quick UDP Internet Connection): 快速 UDP 互联网连接是由 google
提出的使用 udp 进行多路并发传输的协议. 有类似UDP的可靠传输, 支持TLS传输,
支持多路复用技术</li>
</ul>
<h3 id="day5-2-node.js与前端开发实战---欧阳亚东">Day5-2
Node.js与前端开发实战 - 欧阳亚东</h3>
<h4 id="nodejs运行时结构">NodeJS运行时结构</h4>
<figure>
<img data-src="./NodeStruct.jpg" alt="Node结构" />
<figcaption aria-hidden="true">Node结构</figcaption>
</figure>
<ul>
<li>第一层:
<ul>
<li><code>node-cron</code>: 主要用来执行定时任务（源码来自社区）</li>
<li><code>node-inspector</code>: 调试工具</li>
<li>npm</li>
<li>用户代码</li>
</ul></li>
<li>第二层:
<ul>
<li>JS核心（使用JS编写）</li>
<li>N-API: 与其他进程的通信机制</li>
</ul></li>
<li>第三层:
<ul>
<li>JS核心（使用C++编写）</li>
</ul></li>
<li>第四层
<ul>
<li>V8: 运行时</li>
<li>libuv: 实现事件循环与操作系统调用API</li>
<li>nghttp2: http2实现</li>
<li>zlib: 压缩库</li>
<li>c-ares: DNS查询</li>
<li>llhttp: http解析</li>
<li>OpenSSL</li>
</ul></li>
</ul>
<h4 id="nodejs运行时特点">NodeJS运行时特点</h4>
<ul>
<li><p>异步（防止阻塞）</p></li>
<li><p>单线程（指的是JS主线程是单线程的）</p>
<p>实际上JS有JS线程, uv线程池（事件循环与系统调用线程, 例如读取文件,
加密解密）, V8任务线程池, V8 inspector诊断线程（用于调试代码,
如果不单独出来的话JS主线程阻塞了也就没法调试了, 有意思吧,
Node中内置一个浏览器的调试工具）</p>
<p>只有JS线程是单线程的</p></li>
<li><p>跨平台（Node封装了大多数操作系统API）</p></li>
</ul>
<h4 id="node安装调试与部署">Node安装调试与部署</h4>
<p><strong>如何安装Node</strong></p>
<ul>
<li>不使用原生包, 毕竟更新速度快, 不同npm包还可能要求不同版本的Node</li>
<li>Mac, Linux使用<code>nvm</code></li>
<li>windows使用<code>nvm4w</code></li>
</ul>
<p><strong>如何使用V8 inspector调试Node</strong></p>
<p>命令行执行</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">node</span> --inspect app.js
<span class="token comment"># 看到</span>
Debugger listening on ws://127.0.0.1:9229/575f2d97-70cb-48ed-ae5d-1e7389b8c461
For help, see: https://nodejs.org/en/docs/inspector</code></pre>
<p>毕竟用的是V8的调试工具, 打开网址, 直接看到一个全屏的DevTools</p>
<p><strong>部署</strong></p>
<ul>
<li>进程守护: PM2</li>
<li>多进程: cluster</li>
<li>日志记录</li>
</ul>
<h3 id="day6-1-初识webgl---月影">Day6-1 初识WebGL - 月影</h3>
<p><strong>现代图像系统</strong></p>
<ul>
<li>光栅(Raster):几乎所有的现代图形系统都是基于光栅来绘制图形的,
光栅就是指构成图像的像素阵列.</li>
<li>像素（Pixel):一个像素对应图像上的一个点,
它通常保存图像上的某个具体位置的颜色等信息.</li>
<li>帧缓存（Frame Buffer)︰图像存储的数据结构在绘图过程中,
像素信息被存放于帧缓存中, 帧缓存是一块内存地址.</li>
</ul>
<p><strong>WebGL绘图的基本过程</strong></p>
<pre class="mermaid">graph LR

计算顶点数据[计算顶点数据] --> 顶点着色器(顶点着色器-轮廓处理) --> 片元着色器着色器(片元着色器-光栅处理) --光栅化数据--> 帧缓存[帧缓存] --> 输出到显示设备</pre>
<p><strong>JS的WebGL调用流程</strong></p>
<ol type="1">
<li>创建WebGL上下文（通过<code>canvas.getContext('webgl')</code>）</li>
<li>创建WebGL Program</li>
<li>将数据存入缓冲区</li>
<li>将缓冲区数据读取到GPU</li>
<li>GPU 执行WebGL程序, 输出结果</li>
</ol>
<p><strong>WebGL绘制多边形</strong>: 三角剖分</p>
<p><strong>trandform原理</strong></p>
平移 <span class="math display">\[
\begin{equation}
\left\{\begin{array}{l}x=x_{0}+x_{1} \\y=y_{0}+y_{1}\end{array}\right.
\end{equation}
\]</span> 旋转 $$ <span class="math display">\[\begin{equation}
\left\{\begin{array}{l}x=x_{0} \cos \theta-y_{0} \sin \theta \\y=x_{0}
\sin \theta+y_{0} \cos \theta\end{array}\right.

\ \ \ \ \ \ \ \ \ \ \ \
\left(\begin{array}{l}x
\\y\end{array}\right)=\left(\begin{array}{cc}\cos \theta &amp; -\sin
\theta \\\sin \theta &amp; \cos \theta\end{array}\right)
\times\left(\begin{array}{l}x_{0} \\y_{0}\end{array}\right)
\end{equation}\]</span>rray}{l}x \y\end{array})=(
<span class="math display">\[\begin{array}{cc}\cos \theta &amp; -\sin
\theta \\\sin \theta &amp; \cos \theta\end{array}\]</span>
) (
<span class="math display">\[\begin{array}{l}x_{0}
\\y_{0}\end{array}\]</span>
<p>) \end{equation} <span class="math display">\[
缩放
\]</span> <span class="math display">\[\begin{equation}
\left\{\begin{array}{l}x=s_{x} x_{0} \\y=s_{y} y_{0}\end{array}\right.
\ \ \ \ \ \ \ \ \ \ \ \
\left(\begin{array}{l}x
\\y\end{array}\right)=\left(\begin{array}{cc}s_{x} &amp; 0 \\0 &amp;
s_{y}\end{array}\right) \times\left(\begin{array}{l}x_{0}
\\y_{0}\end{array}\right)

\end{equation}\]</span>\end{equation} $$ 他们都是线性变化,
所以这些变化是可以同时进行的（通过矩阵相乘实现新变化）</p>
<p><strong>3D标准模型的四个齐次矩阵</strong></p>
<ol type="1">
<li>投影矩阵Projection Matrix</li>
<li>模型矩阵Model Matrix</li>
<li>视图矩阵View Matrix</li>
<li>法向量矩阵Normal Matrix</li>
</ol>
<h3 id="day6-2-web开发的安全之旅---刘宇晨">Day6-2 Web开发的安全之旅 -
刘宇晨</h3>
<h4 id="xss跨站脚本攻击">XSS跨站脚本攻击</h4>
<p>将恶意脚本字符串注入页面DOM(例如功能是直接将用户提交的数据渲染到<code>div</code>中,
结果用户提交了一个<code>&lt;script&gt;&lt;/script&gt;</code>)</p>
<p>特点:</p>
<ul>
<li>难以点击</li>
<li>可以窃取用户信息(cookie, token)</li>
<li>可以操作UI</li>
</ul>
<p><strong>存储型XSS攻击</strong></p>
<p>将恶意脚本存储到数据库中（比如视频中）,
所有读取数据的人都会被攻击</p>
<p><strong>反射型XSS攻击</strong></p>
<p>有点像服务器端渲染, 用户把包含script标签的内容作为参数发送到服务器,
服务器返回含有script标签的处理结果</p>
<p>例如: 希望实现一个功能, 用户提交自己的名字<code>name=zhangsan</code>,
服务器返回<code>&lt;div&gt;hello zhangsan&lt;/div&gt;</code>,
但是我提交了一个<code>name=&lt;script&gt;alert('I can run')&lt;/script&gt;</code></p>
<p><strong>基于DOM的XSS攻击</strong></p>
<p>通过修改页面的DOM节点形成的XSS, 称之为DOM Based XSS. 从效果来说,
也是反射型. 反射型和存储型是服务端将提交的内容反馈到了html源码内,
导致触发XSS. 也就是说返回到HTML源码中可以看到触发XSS的代码.
DOM型XSS只与客户端上的JS交互, 也就是说提交的恶意代码, 被放到了JS中执行,
然后显示出来</p>
<p><strong>Mutation-based XSS</strong></p>
<p>利用浏览器的渲染DOM特性发起XSS攻击, 这种攻击一般是对特异浏览器的,
难以被XSS过滤工具检测</p>
<p>例如: 我有一个代码段</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>noscript</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>$&#123;info&#125;<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>demo<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>noscript</span><span class="token punctuation">></span></span></code></pre>
<p>希望用户提交title并返回DOM, 这个看起来是安全的,
但是如果用户提交<code>info = '&lt;/noscript&gt;&lt;img src=x onerror="alert('XSS')"&gt;'</code></p>
<p><pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>noscript</span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">title="&lt;</span>/<span class="token attr-name">noscript</span><span class="token punctuation">></span><span class="token attr-name">&lt;img</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span>x</span> <span class="token special-attr"><span class="token attr-name">onerror</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'XSS'</span><span class="token punctuation">)</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>">demo<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>noscript</span><span class="token punctuation">></span></span></code></pre></p>
<p>浏览器发现<code>&lt;noscript&gt;</code>没有闭合, 就会自动纠正</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>noscript</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span> <span class="token attr-name">title</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>
&lt;/noscript>
&lt;img src=<span class="token punctuation">"</span></span><span class="token attr-name">x"</span> <span class="token special-attr"><span class="token attr-name">onerror</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span><span class="token value javascript language-javascript"><span class="token function">alert</span><span class="token punctuation">(</span><span class="token string">'XSS'</span><span class="token punctuation">)</span></span><span class="token punctuation">"</span></span></span><span class="token punctuation">></span></span>
"<span class="token entity named-entity" title="&gt;">&amp;gt;</span>demo<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span></code></pre>
<p>最苟的是浏览器还会把<code>&gt;</code>转义为<code>&amp;gt</code></p>
<h4 id="xss攻击的防御">XSS攻击的防御</h4>
<p>永远不要相信用户提交的内容, 永远不要将用户提交的内容转化为DOM</p>
<ul>
<li>前端防御函数: <code>google-closure-library</code>,
流行框架直接集成</li>
<li>后端防御函数: <code>DOMPurify</code></li>
</ul>
<p>其他防御</p>
<ul>
<li><p>String转义</p></li>
<li><p>SVG扫描(SVG是XML格式的,
可以内置<code>&lt;script&gt;</code>)</p></li>
<li><p>尽量禁止用户设置自定义跳转链接</p></li>
<li><p>尽量禁止用户自定义样式（可以在样式文件里写<code>url(...)</code>）</p></li>
<li><p>CSP内容安全策略:</p>
<p>CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体.
一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,
忽略所有的其他脚本
(包括<strong>内联脚本</strong>和HTML的事件处理属性).</p></li>
</ul>
<h4 id="csrf跨站伪造请求">CSRF跨站伪造请求</h4>
<ul>
<li>可以利用用户权限（cookie）</li>
<li>构造指定http请求</li>
</ul>
<p>例如: 已知用户访问过A银行, 向A银行发送转账请求,
同时浏览器会自动携带银行 Cookie,
银行收到请求一cookie后完成转账（例如利用原生表单实现）</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>form</span> <span class="token attr-name">action</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>https://bankA.com/zhuanhzang/<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>money<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>100000<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>hidden<span class="token punctuation">"</span></span> <span class="token punctuation">></span></span>
	<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>input</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>zhuangei<span class="token punctuation">"</span></span> <span class="token attr-name">value</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>huairendezhanghu<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>hidden<span class="token punctuation">"</span></span> <span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>form</span><span class="token punctuation">></span></span> </code></pre>
<h4 id="csrf防御">CSRF防御</h4>
<ul>
<li><p>服务端通过请求头部的<code>Origin</code>与<code>Referer</code>判断</p>
<p>这个方法不是万能的, 如果遇到毒瘤攻击者, 他可以使用iframe解决跨域问题,
然后iframe里面写表单. 对应方法是设置响应头:
<code>X-frmae-options: deny/sameorigin</code>表示当前页面不能被作为iframe/当前页面若是作为iframe只能作为同源页面的iframe</p></li>
<li><p>要求提供 token</p>
<p>但凡是一个正常的请求, 流程应该都是浏览器先请求页面再请求API,
浏览器请求页面后服务器返回页面与token,
浏览器请求API的时候要求带上token</p></li>
<li><p>尽量不把get与post请求做成一个回调(<code>app.all('',()=&gt;&#123;&#125;)</code>)</p></li>
<li><p><code>SameSite Cookie</code>属性:
在cookie下发的时候设置页面的Cookie只能为页面所用,
其他页面请求的时候不能带上</p></li>
<li><p>Node中间件</p></li>
</ul>
<h4 id="注入攻击">注入攻击</h4>
<p><strong>SQL注入攻击</strong></p>
<p>执行恶意SQL语句, 例如</p>
<p>服务器代码</p>
<pre class="language-js" data-language="js"><code class="language-js">app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/login'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">params</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">sql</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">
    SELECT * from userTable
    WHERE userName = </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>params<span class="token punctuation">.</span>body<span class="token punctuation">.</span>userName<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">
    AND pwd = </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>params<span class="token punctuation">.</span>body<span class="token punctuation">.</span>pwd<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">
    </span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">sucess</span><span class="token operator">:</span> <span class="token operator">!</span><span class="token operator">!</span>result<span class="token punctuation">.</span>length
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre>
<p>客户端请求</p>
<pre class="language-json" data-language="json"><code class="language-json"><span class="token punctuation">&#123;</span>
	userName<span class="token operator">:</span> 'any; drop table userTable;' 
	pwd<span class="token operator">:</span> '<span class="token number">123</span>'
<span class="token punctuation">&#125;</span></code></pre>
<p><strong>CLI注入与OS command注入</strong></p>
<p>例如: 有一个pdf转换网站, 服务器代码</p>
<pre class="language-js" data-language="js"><code class="language-js">app<span class="token punctuation">.</span><span class="token function">get</span><span class="token punctuation">(</span><span class="token string">'/transform/pdf2anytype'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">params</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> source <span class="token operator">=</span> params<span class="token punctuation">.</span>body<span class="token punctuation">.</span>pdfSrc<span class="token punctuation">;</span>
  <span class="token function">exec</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">pandoc -i </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>source<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string"> -o </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>params<span class="token punctuation">.</span>outType<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span>
  <span class="token keyword">return</span> cos<span class="token punctuation">[</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">source.</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>outType<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre>
<p>用户请求</p>
<pre class="language-json" data-language="json"><code class="language-json"><span class="token punctuation">&#123;</span>
	source<span class="token operator">:</span> /path/link/to/<span class="token number">123</span> .pdf
	outType<span class="token operator">:</span> 'shutdown -P now'
<span class="token punctuation">&#125;</span></code></pre>
<p>一般这种攻击的目的就是: 攻击passwd, shadow, ssh, nginx配置</p>
<p><strong>SSRF服务端伪造请求</strong></p>
<p>让服务器请求内网才可以访问的请求</p>
<h4 id="注入防御">注入防御</h4>
<ul>
<li><strong>SQL注入</strong>: 使用<code>prepared statement</code></li>
<li><strong>CLI注入</strong>: 最小权限原则, 系统设置白名单</li>
<li><strong>SSRF</strong>: 访问内网权限控制 v</li>
</ul>
<h4 id="dos拒绝服务攻击">DoS拒绝服务攻击</h4>
<p><strong>基于贪婪匹配正则匹配的ReDoS攻击</strong></p>
<p>后端服务器在进行正则匹配的时候通过回溯法进行多次匹配</p>
<p>计算机在处理正则表达式的时候可以说是非常愚蠢,
虽然看上去它们有很强的计算能力.
当你需要用<code>x*y</code>表达式对字符串<code>xxxxxxxxxxxxxx</code>进行匹配时,
任何人都可以迅速告诉你无匹配结果, 因为这个字符串不包含字符y.
但是计算机的正则表达式引擎并不知道！它将执行以下操作</p>
<pre class="language-none"><code class="language-none">xxxxxxxxxxxxxx # 不匹配
xxxxxxxxxxxxxx # 回溯
xxxxxxxxxxxxx  # 不匹配
xxxxxxxxxxxxx  # 回溯
xxxxxxxxxxxx   # 不匹配
xxxxxxxxxxxx   # 回溯
xxxxxxxxxxx    # 不匹配
xxxxxxxxxxx    # 回溯

&gt;&gt;很多很多步骤 

xx             # 不匹配
x              # 回溯
x              # 不匹配
               # 无匹配结果

你不会以为结束了吧？这只是第一步！

现在, 正则表达式引擎将从第二个x开始匹配, 然后是第三个, 然后是第四个, 依此类推到第14个x. 

最终总步骤数为256. </code></pre>
<p><strong>分布式拒绝服务攻击DDoS</strong></p>
<p>大力出奇迹, 莽就完事, 消耗大量带宽, 占用尽量大的连接数</p>
<h4 id="dos防御">DoS防御</h4>
<p><strong>ReDoS</strong></p>
<ul>
<li><strong>Code Review</strong>:
尽量使用非贪婪匹配（使用<code>?</code>）</li>
<li><strong>代码扫描与正则性能测试</strong></li>
<li><strong>不使用用户提供的正则</strong></li>
</ul>
<p><strong>DDoS</strong></p>
<ul>
<li>流量过</li>
<li>嗯刚</li>
</ul>
<h3 id="day7-构建webpack知识体系---范文杰">Day7 构建webpack知识体系 -
范文杰</h3>
<h4 id="什么是webpack">什么是Webpack</h4>
<p>前端项目由多种资源文件(HTML, CSS, JS, less, Vue, jsx, png...)构成,
以前我们需要手动管理这些文件, 这些文件不仅多,
而且存在复杂的依赖关系与编译需求, 极大的影响了开发效率</p>
<p><strong>为了解决JS模块化与资源管理问题</strong>,
出现了前端工程化工具, 最开始有Gulp, Grunt, Require.JS, browerify,
后来又出现了rollup.js, Vite, Webpack</p>
<p><strong>Webpack本质是一个前端资源编译, 打包工具</strong></p>
<ul>
<li>编译: 将非JS文件(图片等)编译为JS兼容的内容</li>
<li>打包: 将编译好的内容进行打包,
使得浏览器可以运行不同的模块化语法与API</li>
</ul>
<p><strong>Webpack的特性</strong></p>
<ul>
<li>多份资源文件打包成一个Bundle, 使用统一的资源文件模型</li>
<li>支持Babel, Eslint, TS, CoffeScript, Less, Sass,
可以对高级特性语法进行编译</li>
<li>支持模块化处理css, 图片等资源文件</li>
<li>支持HMR＋开发服务器</li>
<li>支持持续监听, 持续构建支持代码分离</li>
<li>支持 Tree-shaking</li>
<li>支持Sourcemap</li>
</ul>
<h4 id="webpack打包流程">Webpack打包流程</h4>
<pre class="mermaid">graph LR
从entry入口开始处理 --> 从entry文件开始进行依赖解析 --> 根据module中配置对非JS文件进行解析 --> 资源合并打包转化为浏览器可用JS

根据module中配置对非JS文件进行解析 --递归直到解析完成--> 从entry文件开始进行依赖解析</pre>
<h4 id="使用webpack">使用Webpack</h4>
<p>安装依赖</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">sudo</span> <span class="token function">npm</span> <span class="token function">install</span> webpack-cli -g
<span class="token function">npm</span> <span class="token function">install</span> webpack-cli webpack -dev
<span class="token builtin class-name">echo</span> <span class="token string">'export PATH="./node_modules/.bin:$PATH"'</span> <span class="token operator">>></span> ~/.zshrc    <span class="token comment"># zsh安装</span></code></pre>
<p>编辑配置文件</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> <span class="token punctuation">&#123;</span>resolve<span class="token punctuation">&#125;</span> <span class="token operator">=</span> <span class="token function">require</span><span class="token punctuation">(</span><span class="token string">'path'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>      <span class="token comment">// 使用path调用目录绝对路径</span>

module<span class="token punctuation">.</span>exports<span class="token operator">=</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">entry</span><span class="token operator">:</span> <span class="token string">'./src/js/index.js'</span><span class="token punctuation">,</span>         <span class="token comment">// 入口文件地址</span>
    <span class="token literal-property property">output</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token literal-property property">filename</span><span class="token operator">:</span> <span class="token string">"built.js"</span><span class="token punctuation">,</span> 				<span class="token comment">// string (default)</span>
        <span class="token literal-property property">path</span><span class="token operator">:</span> <span class="token function">resolve</span><span class="token punctuation">(</span>__dirname<span class="token punctuation">,</span> <span class="token string">'build'</span><span class="token punctuation">)</span>   <span class="token comment">// 保存文件路径, 转换为绝对路径</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">module</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token literal-property property">mode</span><span class="token operator">:</span> <span class="token string">'development'</span>
    <span class="token comment">// mode: 'production'</span>
<span class="token punctuation">&#125;</span> 
</code></pre>
<p>编译打包</p>
<pre class="language-bash" data-language="bash"><code class="language-bash">npx webpack</code></pre>
<p><strong>配置分类</strong></p>
<p>配置文件是Webpack最复杂的部分, 可以将配置分为两类</p>
<ul>
<li><p>流程类(打包四步骤之内的内容)</p>
<p>作用域流程中的某个环节, 直接影响打包效果</p></li>
<li><p>工具类(不在四步骤之内的, 例如treeshaking)</p>
<p>在主流程之外提供更多工程化能力</p></li>
</ul>
<p><strong>流程类配置</strong></p>
<ul>
<li><code>entry</code>阶段相关
<ul>
<li><code>entry</code></li>
<li><code>context</code></li>
</ul></li>
<li>依赖解析相关
<ul>
<li><code>resolve</code></li>
<li><code>externals</code></li>
</ul></li>
<li>文件编译相关
<ul>
<li><code>module</code></li>
</ul></li>
<li>打包处理相关
<ul>
<li><code>optimization</code></li>
<li><code>mode</code></li>
<li><code>target</code></li>
</ul></li>
</ul>
<p><strong>工具类配置</strong></p>
<ul>
<li>开发效率相关: <code>watch</code>, <code>devtool</code>,
<code>devServer</code></li>
<li>性能优化相关: <code>cache</code>, <code>performance</code></li>
<li>日志相关: <code>stats</code>,
<code>infrastructureLogging</code></li>
<li>其他: <code>amd</code>, <code>bail</code></li>
</ul>
<p><strong>流程类配置</strong></p>
<ul>
<li><p><code>entry</code>, <code>output</code>: 输入输出文件</p></li>
<li><p>处理CSS文件</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> style-loader css-loader -dev</code></pre>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">module</span><span class="token operator">:</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">rules</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token punctuation">&#123;</span>
        <span class="token comment">// 匹配什么文件(以css结尾)</span>
        <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.css$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
        <span class="token comment">// css-loader可以将css转化为CommonJS模块, 内容是样式字符串</span>
        <span class="token comment">// style-loader可以JS中的css样式资源创建style插入进去</span>
        <span class="token comment">// 注意, use中的执行顺序是自右向左</span>
        <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>处理less文件</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> <span class="token function">less</span> less-loader -dev</code></pre>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.less$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">use</span><span class="token operator">:</span> <span class="token punctuation">[</span><span class="token string">'style-loader'</span><span class="token punctuation">,</span> <span class="token string">'css-loader'</span><span class="token punctuation">,</span><span class="token string">'less-loader'</span><span class="token punctuation">]</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>引入Babel</p>
<pre class="language-bash" data-language="bash"><code class="language-bash"><span class="token function">npm</span> <span class="token function">install</span> babel-loader <span class="token punctuation">\</span>
@babel/core @babel/preset-env core-js <span class="token punctuation">\</span>
@babel/polyfill -dev</code></pre>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">test</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">\.js$</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">exclude</span><span class="token operator">:</span> <span class="token regex"><span class="token regex-delimiter">/</span><span class="token regex-source language-regex">node_modules</span><span class="token regex-delimiter">/</span></span><span class="token punctuation">,</span>
  <span class="token literal-property property">loader</span><span class="token operator">:</span> <span class="token string">'babel-loader'</span><span class="token punctuation">,</span>
  <span class="token literal-property property">options</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 预设:指示 babel 做怎么样的兼容性处理</span>
    <span class="token literal-property property">presets</span><span class="token operator">:</span> <span class="token punctuation">[</span>
      <span class="token punctuation">[</span>
        <span class="token string">'@babel/preset-env'</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#123;</span>
          <span class="token comment">// 按需加载</span>
          <span class="token literal-property property">useBuiltIns</span><span class="token operator">:</span> <span class="token string">'usage'</span><span class="token punctuation">,</span>
          <span class="token comment">// 指定 core-js 版本</span>
          <span class="token literal-property property">corejs</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">version</span><span class="token operator">:</span> <span class="token number">3</span><span class="token punctuation">,</span>
          <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token comment">// 指定兼容性做到哪个版本浏览器</span>
          <span class="token literal-property property">targets</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
            <span class="token literal-property property">chrome</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">firefox</span><span class="token operator">:</span> <span class="token string">'60'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">ie</span><span class="token operator">:</span> <span class="token string">'9'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">safari</span><span class="token operator">:</span> <span class="token string">'10'</span><span class="token punctuation">,</span>
            <span class="token literal-property property">edge</span><span class="token operator">:</span> <span class="token string">'17'</span><span class="token punctuation">,</span>
          <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token punctuation">]</span><span class="token punctuation">,</span>
    <span class="token punctuation">]</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>打包HTML(需要用到插件)</p>
<pre class="language-npm" data-language="npm"><code class="language-npm">npm install html-webpack-plugin </code></pre>
<p>作为插件, 在使用的时候需要手动引入, webpack.config.js</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> HtmlWebpackPlugin <span class="token operator">=</span> <span class="token function">require</span> <span class="token punctuation">(</span><span class="token string">'html-webpack-plugin'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token comment">// ...</span>
<span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span>
    <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span></code></pre>
<p>这里直接生成会发现 build 文件夹中多了一个 index.html
并且会自动引用所有输出资源, 想要指定压缩的 html 文件, 只需要</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token literal-property property">plugins</span><span class="token operator">:</span><span class="token punctuation">[</span>
  <span class="token keyword">new</span> <span class="token class-name">HtmlWebpackPlugin</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
    <span class="token literal-property property">template</span><span class="token operator">:</span> <span class="token string">'./src/index.html'</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">]</span></code></pre>
<p>值得注意的是我们不要再次引用 js 资源了</p></li>
</ul>
<p><strong>工具类配置</strong></p>
<ul>
<li><p>模块热替换 HMR</p>
<p>存在问题, 当一个文件变化时, 全部文件都会重新打包, 希望与 GLUP 一样,
实现文件热更新</p>
<ul>
<li><p><code>devServer</code> 中添加属性
<code>hot = true</code></p></li>
<li><p>修改入口文件:
<code>entry: ['./src/js/index.js', './src/index.html']</code></p></li>
<li><p>修改 JS 文件, 在末尾加入:</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">if</span><span class="token punctuation">(</span>module<span class="token punctuation">.</span>hot<span class="token punctuation">)</span><span class="token punctuation">&#123;</span>     <span class="token comment">// 如果开启了热加载</span>
    module<span class="token punctuation">.</span>hot<span class="token punctuation">.</span><span class="token function">accept</span><span class="token punctuation">(</span><span class="token string">'test.js'</span><span class="token punctuation">,</span><span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>   <span class="token comment">// 监控test文件, 如果变化不重新编译, 只调用回调函数</span>
        <span class="token function">work</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>运行</p>
<pre class="language-bash" data-language="bash"><code class="language-bash">npx webpack server</code></pre></li>
</ul></li>
<li><p>Tree-Shaking</p>
<ul>
<li><p>删除没有用到的, 无法到达的, 执行结果不会被使用,
只读不写的代码,</p></li>
<li><div class="sourceCode" id="cb1"><pre
class="sourceCode json"><code class="sourceCode json"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a>  <span class="er">mode:</span> <span class="er">&#39;production&#39;</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>  <span class="er">optomization:</span> <span class="fu">&#123;</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a>      <span class="er">usedExports</span><span class="fu">:</span> <span class="kw">true</span></span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a>  <span class="fu">&#125;</span></span></code></pre></div></li>
<li><p>部分 webpack 版本会删除 css 文件, 需要在 package.json 中设置
<code>"sideEffects": ["*.css", "*.less"]</code></p></li>
</ul></li>
</ul>
<p><a
target="_blank" rel="noopener" href="https://www.liukairui.cc/article/前端构建工具Grunt+Gulp+webpack/#webpack">更多配置见此</a></p>
<p><strong>HMR原理</strong></p>
<ol type="1">
<li>使用 <code>webpack-dev-server</code> (后面简称 WDS)托管静态资源,
同时以 Runtime 方式注入 HMR 客户端代码</li>
<li>浏览器加载页面后, 与 WDS 建立 WebSocket 连接</li>
<li>Webpack 监听到文件变化后, 增量构建发生变更的模块, 并通过 WebSocket
发送 <code>hash</code> 事件</li>
<li>浏览器接收到 <code>hash</code> 事件后, 请求 <code>manifest</code>
资源文件, 确认增量变更范围</li>
<li>浏览器加载发生变更的增量模块</li>
<li>Webpack 运行时触发变更模块的 <code>module.hot.accept</code> 回调,
执行代码变更逻辑</li>
</ol>
<h4 id="loader组件">Loader组件</h4>
<p>职责: 将非标准JS资源处理为JS资源模块</p>
<p>执行: 链式调用, 分为两个阶段,</p>
<ul>
<li>pitch阶段:
将use数组中的模块正向执行直到执行结束或遇到<code>return</code></li>
<li>执行阶段: 将use数组中模块反向执行</li>
</ul>
<p>loader的基本结构</p>
<pre class="language-js" data-language="js"><code class="language-js">module<span class="token punctuation">.</span><span class="token function-variable function">exports</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token parameter">source<span class="token punctuation">,</span> sourceMap<span class="token operator">?</span><span class="token punctuation">,</span> data<span class="token operator">?</span></span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> 
    <span class="token comment">// source 为 loader 的输入</span>
    <span class="token comment">// 可能是文件内容, 也可能是上一个 loader 处理结果</span>
    <span class="token keyword">return</span> source<span class="token punctuation">;</span> 
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
<h4 id="plugin组件">Plugin组件</h4>
<p><strong>为什么要引入插件模式</strong>: 对于庞大的项目, 迭代成本很高,
上手难度也很大. 我们希望引入插件模式, 将核心代码与扩展功能分开,
这种模式使得核心代码变得封闭, 仅对插件开放</p>
<p>插件的基本结构: 插件依赖于钩子</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">SomePlugin</span> <span class="token punctuation">&#123;</span>
	<span class="token function">apply</span><span class="token punctuation">(</span><span class="token parameter">compiler</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
		compiler<span class="token punctuation">.</span>hooks<span class="token punctuation">.</span>thisCompilation<span class="token punctuation">.</span><span class="token function">tap</span><span class="token punctuation">(</span> <span class="token string">'SomePlugin'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token parameter">compilation</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>告诉webpack</p>
<ul>
<li>在什么时候执行: 调用钩子函数</li>
<li>上下文是什么: 回调的参数</li>
<li>与webpack交互的函数: 上下文对象中的函数</li>
</ul>
<h4 id="如何学习webpack">如何学习Webpack</h4>
<ul>
<li><p>Step1: 跑起来</p>
<ul>
<li>理解打包流程</li>
<li>熟练掌握常用配置项, Loader, 插件的使用方法, 能够灵活搭建集成Vue,
React, Babel, Eslint, Less, Sass, 图片处理等工具的Webpack 环境</li>
<li>掌握常见脚手架工具的用法, 例如: Vue—cli, create—react-app, <span
class="citation" data-cites="angular/cli">@angular/cli</span></li>
</ul></li>
<li><p>Step2: 写Loader/Plugin</p>
<ul>
<li>理解Loader, Plugin机制, 能够自行开发Webpack组件</li>
<li>理解常见性能优化手段, 并能用于解决实际问题</li>
<li>理解前端工程化概念与生态现状</li>
</ul></li>
<li><p>Step3: 源码</p>
<p>阅读源码, 理解Webpack编译, 打包原理, 甚至能够参与共建</p></li>
</ul>
<p>知识点:</p>
<figure>
<img data-src="webpack5-mindmap.png" alt="webpack5结构" />
<figcaption aria-hidden="true">webpack5结构</figcaption>
</figure>
<h3 id="day8-1-typescript入门---林皇">Day8-1 TypeScript入门 - 林皇</h3>
<h4 id="js与ts">JS与TS</h4>
<table>
<thead>
<tr class="header">
<th>项目</th>
<th>JS</th>
<th>TS</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>变量类型</td>
<td>动态类型</td>
<td>静态类型</td>
</tr>
<tr class="even">
<td>语言类型</td>
<td>弱类型</td>
<td>弱类型</td>
</tr>
</tbody>
</table>
<ul>
<li><p>动/静态类型语言</p>
<p>动态类型: 变量只有在执行的时候才知道具体的(在运行时)</p>
<p>静态类型: 变量需要提前定义语言类型(在运行前)</p></li>
<li><p>强/弱类型语言</p>
<p>强类型语言: 不同变量之间不能隐式转换</p>
<p>弱类型语言: 不同变量之间可以隐式转换</p></li>
</ul>
<p>TS的优势:</p>
<ul>
<li>可读性高</li>
<li>可维护性高(编译的时候处理部分问题), 稳定性好</li>
<li>支持渐进引入与升级</li>
<li>兼容JS</li>
</ul>
<h4 id="基础语法">基础语法</h4>
<ul>
<li><p>基础数据类型:<code>string</code>, <code>number</code>,
<code>boolean</code>, <code>null</code>, <code>undefined</code>,
只需要在变量后面使用<code>:type</code>就可以声明类型</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">const</span> w <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>			<span class="token comment">// JS</span>
<span class="token keyword">const</span> w<span class="token operator">:</span><span class="token builtin">number</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>		<span class="token comment">// TS</span></code></pre></li>
<li><p>其他基础数据类型:</p>
<ul>
<li><p>数组</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">let</span> list<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">[</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> list<span class="token operator">:</span> <span class="token builtin">Array</span><span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>		<span class="token comment">// 另一种方法</span>
<span class="token keyword">interface</span> <span class="token class-name">IArr</span><span class="token punctuation">&#123;</span>								<span class="token comment">// 另一种方法</span>
    <span class="token punctuation">[</span>key<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token builtin">any</span>
<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> list<span class="token operator">:</span>IArr <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span><span class="token number">2</span><span class="token punctuation">,</span><span class="token number">3</span><span class="token punctuation">]</span></code></pre></li>
<li><p>元组: 表示一个已知元素数量和类型的数组, 各元素的类型不必相同.</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">let</span> x<span class="token operator">:</span> <span class="token punctuation">[</span><span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token builtin">number</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
x <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token string">'hello'</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// OK</span>
x <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token string">'hello'</span><span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token comment">// Error</span></code></pre>
<p>当访问一个越界的元素, 会使用联合类型替代:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript">x<span class="token punctuation">[</span><span class="token number">3</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token string">'world'</span><span class="token punctuation">;</span> <span class="token comment">// OK, 字符串可以赋值给(string | number)类型</span>
x<span class="token punctuation">[</span><span class="token number">6</span><span class="token punctuation">]</span> <span class="token operator">=</span> <span class="token boolean">true</span><span class="token punctuation">;</span> 	<span class="token comment">// Error, 布尔不是(string | number)类型</span></code></pre></li>
<li><p>枚举: 可以为一组数值赋予友好的名字</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">enum</span> Color <span class="token punctuation">&#123;</span>Red<span class="token punctuation">,</span> Green<span class="token punctuation">,</span> Blue<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> c<span class="token operator">:</span> Color <span class="token operator">=</span> Color<span class="token punctuation">.</span>Green<span class="token punctuation">;</span></code></pre>
<p>默认情况下, 从<code>0</code>开始为元素编号.
你也可以手动的指定成员的数值. 例如, 我们将上面的例子改成从
<code>1</code>开始编号:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">enum</span> Color <span class="token punctuation">&#123;</span>Red <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> Green<span class="token punctuation">,</span> Blue<span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> c<span class="token operator">:</span> Color <span class="token operator">=</span> Color<span class="token punctuation">.</span>Green<span class="token punctuation">;</span></code></pre>
<p>或者, 全部都采用手动赋值:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">enum</span> Color <span class="token punctuation">&#123;</span>Red <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">,</span> Green <span class="token operator">=</span> <span class="token number">2</span><span class="token punctuation">,</span> Blue <span class="token operator">=</span> <span class="token number">4</span><span class="token punctuation">&#125;</span>
<span class="token keyword">let</span> c<span class="token operator">:</span> Color <span class="token operator">=</span> Color<span class="token punctuation">.</span>Green<span class="token punctuation">;</span></code></pre></li>
<li><p><code>any</code>: 不指定</p></li>
<li><p><code>void</code>: 表示没有任何类型. 当一个函数没有返回值时,
你通常会见到其返回值类型是 <code>void</code></p></li>
<li><p><code>null</code> 和 <code>undefined</code>:
<code>undefined</code>和<code>null</code>两者各自有自己的类型分别叫做<code>undefined</code>和<code>null</code>.
和 <code>void</code>相似, 它们的本身的类型用处不是很大:</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token keyword">let</span> u<span class="token operator">:</span> <span class="token keyword">undefined</span> <span class="token operator">=</span> <span class="token keyword">undefined</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> n<span class="token operator">:</span> <span class="token keyword">null</span> <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span></code></pre>
<p>默认情况下<code>null</code>和<code>undefined</code>是所有类型的子类型.
就是说你可以把
<code>null</code>和<code>undefined</code>赋值给<code>number</code>类型的变量.</p></li>
<li><p><code>never</code>: 类型表示的是那些永不存在的值的类型. 例如:
<code>never</code>类型是那些总是会抛出异常或根本就不会有返回值的函数表达式或箭头函数表达式的返回值类型;
变量也可能是 <code>never</code>类型,
当它们被永不为真的类型保护所约束时.</p>
<p><code>never</code>类型是任何类型的子类型, 也可以赋值给任何类型;
没有类型是<code>never</code>的子类型或可以赋值给<code>never</code>类型(除了<code>never</code>本身之外).
即使 <code>any</code>也不可以赋值给<code>never</code>.</p>
<p>下面是一些返回<code>never</code>类型的函数:</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token comment">// 返回never的函数必须存在无法达到的终点</span>
<span class="token keyword">function</span> <span class="token function">error</span><span class="token punctuation">(</span>message<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">never</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">throw</span> <span class="token keyword">new</span> <span class="token class-name">Error</span><span class="token punctuation">(</span>message<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">// 推断的返回值类型为never</span>
<span class="token keyword">function</span> <span class="token function">fail</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token function">error</span><span class="token punctuation">(</span><span class="token string">"Something failed"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token comment">// 返回never的函数必须存在无法达到的终点</span>
<span class="token keyword">function</span> <span class="token function">infiniteLoop</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">never</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">while</span> <span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p><code>object</code>表示非原始类型, 也就是除<code>number</code>,
<code>string</code>, <code>boolean</code>, <code>symbol</code>,
<code>null</code>或<code>undefined</code>之外的类型.</p>
<p>使用<code>object</code>类型,
就可以更好的表示像<code>Object.create</code>这样的API. 例如:</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token keyword">declare</span> <span class="token keyword">function</span> <span class="token function">create</span><span class="token punctuation">(</span>o<span class="token operator">:</span> object <span class="token operator">|</span> <span class="token keyword">null</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token keyword">void</span><span class="token punctuation">;</span>

<span class="token function">create</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span> prop<span class="token operator">:</span> <span class="token number">0</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// OK</span>
<span class="token function">create</span><span class="token punctuation">(</span><span class="token keyword">null</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// OK</span>

<span class="token function">create</span><span class="token punctuation">(</span><span class="token number">42</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Error</span>
<span class="token function">create</span><span class="token punctuation">(</span><span class="token string">"string"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Error</span>
<span class="token function">create</span><span class="token punctuation">(</span><span class="token boolean">false</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Error</span>
<span class="token function">create</span><span class="token punctuation">(</span><span class="token keyword">undefined</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Error</span></code></pre></li>
</ul></li>
<li><p>对象类型:</p>
<p>使用<code>interface</code>定义一个对象类型</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">const</span> bytedancer<span class="token operator">:</span> IBytedancer <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  name<span class="token operator">:</span> <span class="token string">'liu'</span><span class="token punctuation">,</span>
  id<span class="token operator">:</span> <span class="token number">123</span><span class="token punctuation">,</span>
  sex<span class="token operator">:</span> <span class="token string">'man'</span><span class="token punctuation">,</span>
  hobby<span class="token operator">:</span> <span class="token string">'play'</span><span class="token punctuation">,</span>					<span class="token comment">// 可有可无</span>
  otherProps<span class="token operator">:</span> <span class="token number">333</span><span class="token punctuation">,</span>					<span class="token comment">// 其他属性</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">interface</span> <span class="token class-name">IBytedancer</span> <span class="token punctuation">&#123;</span>				<span class="token comment">// 一般前面加一个I表示接口</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>						<span class="token comment">// 定义属性</span>
  <span class="token keyword">readonly</span> id<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>				<span class="token comment">// 只读属性: 在初始化后不能赋值</span>
  sex<span class="token operator">:</span> <span class="token string">'man'</span> <span class="token operator">|</span> <span class="token string">'woman'</span> <span class="token operator">|</span> <span class="token string">'other'</span><span class="token punctuation">;</span>	<span class="token comment">// 限定内容</span>
  hobby<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>					<span class="token comment">// 可选属性</span>
  <span class="token punctuation">[</span>key<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">]</span><span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">;</span>				<span class="token comment">// 其他属性的key必须是string, value随意</span>
<span class="token punctuation">&#125;</span>
</code></pre></li>
<li><p>函数类型</p>
<p>JS写法</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> <span class="token function-variable function">add2</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter">x<span class="token punctuation">,</span> y</span><span class="token punctuation">)</span> <span class="token operator">=></span> x <span class="token operator">+</span> y<span class="token punctuation">;</span></code></pre>
<p>TS写法: 为每一项加入属性</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">function</span> <span class="token function">add</span><span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> add2 <span class="token operator">=</span> <span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=></span> x <span class="token operator">+</span> y<span class="token punctuation">;</span></code></pre>
<p>TS写法: 整体赋类型</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">const</span> <span class="token function-variable function">add</span><span class="token operator">:</span> <span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function-variable function">number</span> <span class="token operator">=</span> 
  <span class="token keyword">function</span> <span class="token punctuation">(</span>x<span class="token operator">:</span><span class="token builtin">number</span><span class="token punctuation">,</span> y<span class="token operator">:</span><span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span><span class="token builtin">number</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">add2</span><span class="token operator">:</span> <span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token function-variable function">number</span> <span class="token operator">=</span> 
  <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span> <span class="token operator">=></span> x <span class="token operator">+</span> y<span class="token punctuation">;</span></code></pre>
<p>TS写法: 通过接口定义</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Iadd</span> <span class="token punctuation">&#123;</span>
  <span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> add3<span class="token operator">:</span> <span class="token function-variable function">Iadd</span> <span class="token operator">=</span> <span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span> <span class="token operator">=></span> x <span class="token operator">+</span> y<span class="token punctuation">;</span></code></pre>
<p>函数重载</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">function</span> <span class="token function">getDate</span><span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'string'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span> <span class="token comment">// 当type传入的值为'string'时, 传出String类</span>
<span class="token keyword">function</span> <span class="token function">getDate</span><span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'date'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> Date<span class="token punctuation">;</span>     <span class="token comment">// 当type传入的值为'date'时, 传出Date类</span>

<span class="token comment">// 实现函数</span>
<span class="token keyword">function</span> <span class="token function">getDate</span><span class="token punctuation">(</span>
  type<span class="token operator">:</span> <span class="token string">'string'</span> <span class="token operator">|</span> <span class="token string">'date'</span><span class="token punctuation">,</span>  <span class="token comment">// 两种值二选一, 不是说type可以是string类型也可以是date类型, 毕竟JS是动态类型的</span>
  timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span>
<span class="token punctuation">)</span><span class="token operator">:</span> Date <span class="token operator">|</span> <span class="token builtin">string</span> <span class="token punctuation">&#123;</span>          <span class="token comment">// 这里不必一一对应, 会根据开始时候重载的结果判断</span>
  <span class="token keyword">const</span> date <span class="token operator">=</span> timestamp <span class="token operator">?</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>timestamp<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> type <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">?</span> date<span class="token punctuation">.</span><span class="token function">toLocaleString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> date<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>使用<code>interface</code>进行重载</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">IGetDate</span> <span class="token punctuation">&#123;</span>
  <span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'string'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  <span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'date'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> Date<span class="token punctuation">;</span>
  <span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'string'</span> <span class="token operator">|</span> <span class="token string">'date'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> Date<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> getDate<span class="token operator">:</span> <span class="token function-variable function">IGetDate</span> <span class="token operator">=</span> <span class="token punctuation">(</span>type<span class="token punctuation">,</span> timestamp<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> date <span class="token operator">=</span> timestamp <span class="token operator">?</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>timestamp<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> type <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">?</span> date<span class="token punctuation">.</span><span class="token function">toLocaleString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> date<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
<p>报错了,
原因是TS将匿名函数推断为了一个<code>(any, any)=&gt;any</code>,
与<code>IGetDate</code>不匹配,
解决方法是让<code>IGetDate</code>的范围大于匿名函数,
修改返回类型为<code>any</code>即可</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">IGetDate</span> <span class="token punctuation">&#123;</span>
  <span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'string'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">;</span>
  <span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'date'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">;</span>
  <span class="token punctuation">(</span>type<span class="token operator">:</span> <span class="token string">'string'</span> <span class="token operator">|</span> <span class="token string">'date'</span><span class="token punctuation">,</span> timestamp<span class="token operator">?</span><span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> getDate<span class="token operator">:</span> <span class="token function-variable function">IGetDate</span> <span class="token operator">=</span> <span class="token punctuation">(</span>type<span class="token punctuation">,</span> timestamp<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> date <span class="token operator">=</span> timestamp <span class="token operator">?</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span>timestamp<span class="token punctuation">)</span> <span class="token operator">:</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> type <span class="token operator">===</span> <span class="token string">'string'</span> <span class="token operator">?</span> date<span class="token punctuation">.</span><span class="token function">toLocaleString</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">:</span> date<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre></li>
<li><p>泛型</p>
<p>不预先指定类型</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">function</span> <span class="token generic-function"><span class="token function">identity</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token constant">T</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> arg<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">let</span> myIdentity<span class="token operator">:</span> <span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token constant">T</span> <span class="token operator">=</span> identity<span class="token punctuation">;</span></code></pre>
<p>泛型接口</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">GenericIdentityFn</span> <span class="token punctuation">&#123;</span>
    <span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token generic-function"><span class="token function">identity</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token constant">T</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> arg<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">let</span> myIdentity<span class="token operator">:</span> GenericIdentityFn <span class="token operator">=</span> identity<span class="token punctuation">;</span></code></pre>
<p>泛型类</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">class</span> <span class="token class-name">GenericNumber<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span> <span class="token punctuation">&#123;</span>
    zeroValue<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">;</span>
    <span class="token function-variable function">add</span><span class="token operator">:</span> <span class="token punctuation">(</span>x<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">,</span> y<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token constant">T</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">let</span> myGenericNumber <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">GenericNumber<span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">></span></span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
myGenericNumber<span class="token punctuation">.</span>zeroValue <span class="token operator">=</span> <span class="token number">0</span><span class="token punctuation">;</span>
myGenericNumber<span class="token punctuation">.</span><span class="token function-variable function">add</span> <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>x<span class="token punctuation">,</span> y<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token keyword">return</span> x <span class="token operator">+</span> y<span class="token punctuation">;</span> <span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
<p>泛型别名</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name"><span class="token constant">I2</span><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></span> <span class="token operator">=</span> <span class="token constant">I1</span><span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span></code></pre>
<p>泛型约束: 希望泛型被限制在一定范围内(<code>extends</code>,
表示类型约束)</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">Lengthwise</span> <span class="token punctuation">&#123;</span>
    length<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token generic-function"><span class="token function">loggingIdentity</span><span class="token generic class-name"><span class="token operator">&lt;</span><span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token builtin">string</span><span class="token operator">></span></span></span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token constant">T</span> <span class="token punctuation">&#123;</span>
    <span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>arg<span class="token punctuation">.</span>length<span class="token punctuation">)</span><span class="token punctuation">;</span>  <span class="token comment">// Now we know it has a .length property, so no more error</span>
    <span class="token keyword">return</span> arg<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>泛型参数默认类型</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">IGet<span class="token operator">&lt;</span><span class="token constant">T</span> <span class="token operator">=</span> <span class="token builtin">number</span><span class="token operator">></span></span> <span class="token operator">=</span> <span class="token punctuation">(</span>target<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token constant">T</span><span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> get<span class="token operator">:</span> IGet<span class="token operator">&lt;</span><span class="token builtin">string</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">(</span>d<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span>d<span class="token punctuation">]</span><span class="token punctuation">;</span>		<span class="token comment">// T = string</span>
<span class="token keyword">const</span> get2<span class="token operator">:</span> <span class="token function-variable function">IGet</span> <span class="token operator">=</span> <span class="token punctuation">(</span>d<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">[</span>d<span class="token punctuation">]</span><span class="token punctuation">;</span>				<span class="token comment">// T = number</span></code></pre></li>
<li><p>类型别名与断言</p>
<p><code>type</code>可以定义类型别名</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">INumArr</span> <span class="token operator">=</span> <span class="token builtin">Array</span><span class="token operator">&lt;</span><span class="token builtin">number</span><span class="token operator">></span></code></pre>
<p>类型断言有两种形式. 其一是“尖括号”语法:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">let</span> someValue<span class="token operator">:</span> <span class="token builtin">any</span> <span class="token operator">=</span> <span class="token string">"this is a string"</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> strLength<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token operator">&lt;</span><span class="token builtin">string</span><span class="token operator">></span>someValue<span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span></code></pre>
<p>另一个为<code>as</code>语法:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">let</span> someValue<span class="token operator">:</span> <span class="token builtin">any</span> <span class="token operator">=</span> <span class="token string">"this is a string"</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> strLength<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">=</span> <span class="token punctuation">(</span>someValue <span class="token keyword">as</span> <span class="token builtin">string</span><span class="token punctuation">)</span><span class="token punctuation">.</span>length<span class="token punctuation">;</span></code></pre></li>
<li><p>字符串|数字 字面量(值只能选一个)</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">IAnimal</span> <span class="token operator">=</span> <span class="token string">'cat'</span><span class="token operator">|</span><span class="token string">'dog'</span><span class="token operator">|</span><span class="token string">'mice'</span><span class="token punctuation">;</span>
<span class="token keyword">type</span> <span class="token class-name">age</span> <span class="token operator">=</span> <span class="token number">1</span><span class="token operator">|</span><span class="token number">2</span><span class="token operator">|</span><span class="token number">3</span><span class="token punctuation">;</span></code></pre></li>
</ul>
<h4 id="高级类型">高级类型</h4>
<ul>
<li><p>交叉与联合类型</p>
<ul>
<li><p>联合类型</p>
<p><code>t:IA|IB</code>属性值可以是<code>IA</code>或<code>IB</code>,
不能按照集合中的并来理解</p>
<p><strong>对于属性来说</strong></p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">UnionA</span> <span class="token operator">=</span> <span class="token string">'px'</span> <span class="token operator">|</span> <span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span> <span class="token operator">|</span> <span class="token string">'%'</span><span class="token punctuation">;</span>
<span class="token keyword">type</span> <span class="token class-name">UnionB</span> <span class="token operator">=</span> <span class="token string">'vh'</span> <span class="token operator">|</span> <span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span> <span class="token operator">|</span> <span class="token string">'pt'</span><span class="token punctuation">;</span>
<span class="token keyword">type</span> <span class="token class-name">IntersectionUnion</span> <span class="token operator">=</span> UnionA <span class="token operator">|</span> UnionB<span class="token punctuation">;</span></code></pre>
<p>联合类型的结果为:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token string">'px'</span> <span class="token operator">|</span> <span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span> <span class="token operator">|</span> <span class="token string">'%'</span> <span class="token operator">|</span> <span class="token string">'vh'</span> <span class="token operator">|</span> <span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span> <span class="token operator">|</span> <span class="token string">'pt'</span></code></pre>
<p>对于属性来说, 联合类型确实是具有所有类型的并</p>
<p><strong>对于接口来说</strong></p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IA</span></span> <span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  b<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IB</span></span> <span class="token punctuation">&#123;</span>
  b<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> Date<span class="token punctuation">;</span>
  c<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">IA</span> <span class="token operator">|</span> <span class="token constant">IB</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  arg<span class="token punctuation">.</span>a <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>				<span class="token comment">// error</span>
  arg<span class="token punctuation">.</span>c <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>				<span class="token comment">// error</span>
  arg<span class="token punctuation">.</span>b <span class="token operator">=</span> <span class="token string">'1'</span><span class="token punctuation">;</span>				<span class="token comment">// ok</span>
  arg<span class="token punctuation">.</span>b <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>				<span class="token comment">// ok</span>
  arg<span class="token punctuation">.</span>b <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>		<span class="token comment">// ok</span>
  arg<span class="token punctuation">.</span>b <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token number">1</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">]</span><span class="token punctuation">;</span>		<span class="token comment">// error</span>
  arg <span class="token operator">=</span> <span class="token punctuation">&#123;</span>					<span class="token comment">// ok</span>
    a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
    b<span class="token operator">:</span> <span class="token string">'22'</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>联合类型的结果为:</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  b<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
或
<span class="token punctuation">&#123;</span>
  b<span class="token operator">:</span> <span class="token builtin">string</span> <span class="token operator">|</span> Date<span class="token punctuation">;</span>
  c<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
但是直接访问只能访问到
<span class="token punctuation">&#123;</span>
	b<span class="token operator">:</span> <span class="token builtin">string</span><span class="token operator">|</span> <span class="token builtin">number</span><span class="token operator">|</span> Date<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p><strong>结论: 联合类型对于属性是并, 对于接口是并,
但是单独访问接口内容的时候只能访问交集内容</strong>,
对接口访问时候取交是出于安全考虑</p></li>
<li><p>交叉类型</p>
<p><code>IA &amp; IB</code>:
<code>IA</code>与<code>IB</code>类型的叠加</p>
<p>交叉类型不能完全按照传统集合中的"与"来理解</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token keyword">interface</span> <span class="token class-name">Interface1</span> <span class="token punctuation">&#123;</span>
  id<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">|</span> Date<span class="token punctuation">;</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">interface</span> <span class="token class-name">Interface2</span> <span class="token punctuation">&#123;</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  id<span class="token operator">:</span> <span class="token builtin">number</span> <span class="token operator">|</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">foo</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> Interface1 <span class="token operator">&amp;</span> Interface2<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  arg<span class="token punctuation">.</span>id <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>					<span class="token comment">// ok</span>
  arg<span class="token punctuation">.</span>age <span class="token operator">=</span> <span class="token number">1</span><span class="token punctuation">;</span>					<span class="token comment">// ok</span>
  arg<span class="token punctuation">.</span>name <span class="token operator">=</span> <span class="token string">'12'</span><span class="token punctuation">;</span>				<span class="token comment">// ok</span>
  arg<span class="token punctuation">.</span>id <span class="token operator">=</span> <span class="token string">'12'</span><span class="token punctuation">;</span>				<span class="token comment">// error</span>
  arg<span class="token punctuation">.</span>id <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>			<span class="token comment">// error</span>
  arg <span class="token operator">=</span> <span class="token punctuation">&#123;</span>						
    id<span class="token operator">:</span> <span class="token string">'123'</span><span class="token punctuation">,</span>					<span class="token comment">// error</span>
    age<span class="token operator">:</span> <span class="token number">12</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
  arg <span class="token operator">=</span> <span class="token punctuation">&#123;</span>						<span class="token comment">// ok</span>
    id<span class="token operator">:</span> <span class="token number">123</span><span class="token punctuation">,</span>
    age<span class="token operator">:</span> <span class="token number">12</span><span class="token punctuation">,</span>
    name<span class="token operator">:</span> <span class="token string">'23'</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>交叉类型的类型为</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token punctuation">&#123;</span>
	id<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
	age<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>对于接口来说, 交叉类型确实是具有所有接口类型的所有特性</p>
<p>对于联合类型, 情况就有点不同了.</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token keyword">type</span> <span class="token class-name">UnionA</span> <span class="token operator">=</span> <span class="token string">'px'</span> <span class="token operator">|</span> <span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span> <span class="token operator">|</span> <span class="token string">'%'</span><span class="token punctuation">;</span>
<span class="token keyword">type</span> <span class="token class-name">UnionB</span> <span class="token operator">=</span> <span class="token string">'vh'</span> <span class="token operator">|</span> <span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span> <span class="token operator">|</span> <span class="token string">'pt'</span><span class="token punctuation">;</span>
<span class="token keyword">type</span> <span class="token class-name">IntersectionUnion</span> <span class="token operator">=</span> UnionA <span class="token operator">&amp;</span> UnionB<span class="token punctuation">;</span></code></pre>
<p>交叉类型 <code>IntersectionUnion</code> 的类型为:</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token string">'em'</span> <span class="token operator">|</span> <span class="token string">'rem'</span></code></pre>
<p><strong>结论: 对于接口是并, 对于属性类型是交,
单独访问接口内容的时候可以访问并集内容</strong></p></li>
<li><p>举例</p>
<p>希望表示的两种类型书的书单</p>
<p><pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">IHistoryBook</span> <span class="token punctuation">&#123;</span>
  author<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  type<span class="token operator">:</span> <span class="token string">'history'</span><span class="token punctuation">;</span>
  range<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
    
<span class="token keyword">interface</span> <span class="token class-name">IStoryBook</span> <span class="token punctuation">&#123;</span>
  author<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  type<span class="token operator">:</span> <span class="token string">'story'</span><span class="token punctuation">;</span>
  theme<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>
    
<span class="token keyword">type</span> <span class="token class-name">IBookArr</span> <span class="token operator">=</span> <span class="token builtin">Array</span><span class="token operator">&lt;</span>IHistoryBook <span class="token operator">|</span> IStoryBook<span class="token operator">></span><span class="token punctuation">;</span></code></pre></p>
<p>使用联合与交叉(注意联合与交叉与集合的交并不一样)</p>
<p><pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">IBookArr</span> <span class="token operator">=</span> <span class="token builtin">Array</span><span class="token operator">&lt;</span>
  <span class="token punctuation">&#123;</span>
    author<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span> <span class="token operator">&amp;</span> <span class="token punctuation">(</span>
    <span class="token operator">|</span> <span class="token punctuation">&#123;</span>
        type<span class="token operator">:</span> <span class="token string">'story'</span><span class="token punctuation">;</span>
        theme<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span>
    <span class="token operator">|</span> <span class="token punctuation">&#123;</span>
        type<span class="token operator">:</span> <span class="token string">'history'</span><span class="token punctuation">;</span>
        range<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span>
  <span class="token punctuation">)</span>
<span class="token operator">></span><span class="token punctuation">;</span>
    
<span class="token keyword">const</span> bookarr<span class="token operator">:</span> IBookArr <span class="token operator">=</span> <span class="token punctuation">[</span>
  <span class="token punctuation">&#123;</span> author<span class="token operator">:</span> <span class="token string">'l'</span><span class="token punctuation">,</span> type<span class="token operator">:</span> <span class="token string">'history'</span><span class="token punctuation">,</span> range<span class="token operator">:</span> <span class="token string">'2020-2021'</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#123;</span> author<span class="token operator">:</span> <span class="token string">'k'</span><span class="token punctuation">,</span> type<span class="token operator">:</span> <span class="token string">'story'</span><span class="token punctuation">,</span> theme<span class="token operator">:</span> <span class="token string">'love'</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">]</span><span class="token punctuation">;</span>
    </code></pre></p></li>
</ul></li>
<li><p>类型保护与类型守卫</p>
<p>类型保护: 联合类型中单独访问接口内容的时候只能访问交集内容</p>
<p>我们想根据存在的<code>key</code>判断结果</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IA</span></span> <span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resa<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IB</span></span> <span class="token punctuation">&#123;</span>
  b<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resb<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">getRes</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">IA</span> <span class="token operator">|</span> <span class="token constant">IB</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">!</span><span class="token operator">!</span>arg<span class="token punctuation">.</span>a <span class="token operator">&amp;&amp;</span> arg<span class="token punctuation">.</span>a <span class="token operator">!==</span> <span class="token number">0</span><span class="token punctuation">)</span> <span class="token keyword">return</span> arg<span class="token punctuation">.</span>resb<span class="token punctuation">;</span>		<span class="token comment">// error</span>
  <span class="token keyword">return</span> arg<span class="token punctuation">.</span>resa<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>受到类型保护我们无法单独访问<code>a,b,resa,resb</code></p>
<p>类型守卫: 定义一个函数, 返回值是一个类型谓词, 生效范围为子作用域</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IA</span></span> <span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resa<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IB</span></span> <span class="token punctuation">&#123;</span>
  b<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resb<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">isIA</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">IA</span> <span class="token operator">|</span> <span class="token constant">IB</span><span class="token punctuation">)</span><span class="token operator">:</span> arg <span class="token keyword">is</span> <span class="token constant">IA</span> <span class="token punctuation">&#123;</span>			<span class="token comment">// 返回值为类型谓词(arg是不是IA), 当函数返回为true的时候表示arg一定为IA</span>
  <span class="token keyword">return</span> <span class="token operator">!</span><span class="token operator">!</span><span class="token punctuation">(</span>arg <span class="token keyword">as</span> <span class="token constant">IA</span><span class="token punctuation">)</span><span class="token punctuation">.</span>a<span class="token punctuation">;</span>							<span class="token comment">// 假装是IA并获取a</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">getRes</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">IA</span> <span class="token operator">|</span> <span class="token constant">IB</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token function">isIA</span><span class="token punctuation">(</span>arg<span class="token punctuation">)</span><span class="token punctuation">)</span> <span class="token keyword">return</span> arg<span class="token punctuation">.</span>resa<span class="token punctuation">;</span>
  <span class="token keyword">return</span> arg<span class="token punctuation">.</span>resb<span class="token punctuation">;</span>              <span class="token comment">// 有一点点智能啊</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>有点麻烦, 暂时没有解决的办法, 但是如果两个接口有相同的key,
我们可以通过<code>typeof</code>与<code>instanceof</code>进行判断</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IA</span></span> <span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resa<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  f<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IB</span></span> <span class="token punctuation">&#123;</span>
  b<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resb<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  f<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">getF</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">IA</span> <span class="token operator">|</span> <span class="token constant">IB</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> arg<span class="token punctuation">.</span>f <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token keyword">return</span> arg<span class="token punctuation">.</span>f<span class="token punctuation">.</span>length<span class="token punctuation">;</span>
  <span class="token keyword">return</span> arg<span class="token punctuation">.</span>f<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>			<span class="token comment">// 213</span>
  <span class="token function">getF</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
    a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
    resa<span class="token operator">:</span> <span class="token number">213</span><span class="token punctuation">,</span>
    f<span class="token operator">:</span> <span class="token number">213</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>			<span class="token comment">// 3</span>
  <span class="token function">getF</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
    b<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
    resb<span class="token operator">:</span> <span class="token number">213</span><span class="token punctuation">,</span>
    f<span class="token operator">:</span> <span class="token string">'213'</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>还是蛮智能的,
如果<code>f</code>是一个字符串就可以调用字符串的方法</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IA</span></span> <span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resa<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  f<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">interface</span> <span class="token class-name"><span class="token constant">IB</span></span> <span class="token punctuation">&#123;</span>
  b<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  resb<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
  f<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">function</span> <span class="token function">getRes</span><span class="token punctuation">(</span>arg<span class="token operator">:</span> <span class="token constant">IA</span> <span class="token operator">|</span> <span class="token constant">IB</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token comment">// 类型“IA | IB”上不存在属性“resb”. </span>
  <span class="token comment">// 类型“IA”上不存在属性“resb”. ts(2339)  </span>
  <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token keyword">typeof</span> arg<span class="token punctuation">.</span>f <span class="token operator">===</span> <span class="token string">'string'</span><span class="token punctuation">)</span> <span class="token keyword">return</span> arg<span class="token punctuation">.</span>resb<span class="token punctuation">;</span>
  <span class="token keyword">return</span> arg<span class="token punctuation">.</span>resa<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token builtin">console</span><span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token function">getRes</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
  a<span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">,</span>
  resa<span class="token operator">:</span> <span class="token number">213</span><span class="token punctuation">,</span>
  f<span class="token operator">:</span> <span class="token number">213</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">)</span></code></pre>
<p>看来也不是那么智能,
只能判断被<code>typeof</code>或<code>instanceof</code>的元素,
到也不是不能实现, 还有<code>in</code>类型守卫</p>
<pre class="language-none"><code class="language-none">interface IA &#123;
  a: number;
  resa: number;
&#125;

interface IB &#123;
  b: number;
  resb: number;
&#125;

function getRes(arg: IA | IB) &#123;
  if (&#39;a&#39; in arg) return arg.resa;
  return arg.resb;
&#125;</code></pre></li>
<li><p><code>Record</code>类型与<code>Partial</code></p>
<p>TS内置了一个<code>Partial</code>类型,用于把一个类型的成员属性设置为成可选模式,例如</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">Person</span> <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  name<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
  age<span class="token operator">:</span> <span class="token builtin">number</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p><code>Person</code>类型中有两个成员属性,如果我们要把这个类型赋予变量<code>tom</code>,那<code>tom</code>必须拥有<code>name</code>和<code>age</code>两个属性</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">let</span> tom<span class="token operator">:</span>Person <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
    name<span class="token operator">:</span> <span class="token string">'tom'</span><span class="token punctuation">,</span>
    age<span class="token operator">:</span> <span class="token number">20</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
<p>现在我们要让<code>Person</code>的两个属性都变为可选,可以使用<code>Partial</code>类型进行转换</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">PartialPerson</span> <span class="token operator">=</span> Partial<span class="token operator">&lt;</span>Person<span class="token operator">></span><span class="token punctuation">;</span>

<span class="token keyword">let</span> partialPerson<span class="token operator">:</span> PartialPerson <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  name<span class="token operator">:</span> <span class="token string">'tom'</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
<p>这时<code>PartialPerson</code>的<code>name</code>和<code>age</code>属性都已经变为可选的了</p>
<p>TS内置了一个<code>Record</code>类型,用于定义一个对象的 key 和 value
类型.</p>
<pre class="language-ts" data-language="ts"><code class="language-ts"><span class="token keyword">interface</span> <span class="token class-name">PageInfo</span> <span class="token punctuation">&#123;</span>
  title<span class="token operator">:</span> <span class="token builtin">string</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">type</span> <span class="token class-name">Page</span> <span class="token operator">=</span> <span class="token string">"home"</span> <span class="token operator">|</span> <span class="token string">"about"</span> <span class="token operator">|</span> <span class="token string">"contact"</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> nav<span class="token operator">:</span> Record<span class="token operator">&lt;</span>Page<span class="token punctuation">,</span> PageInfo<span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  about<span class="token operator">:</span> <span class="token punctuation">&#123;</span> title<span class="token operator">:</span> <span class="token string">"about"</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  contact<span class="token operator">:</span> <span class="token punctuation">&#123;</span> title<span class="token operator">:</span> <span class="token string">"contact"</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  home<span class="token operator">:</span> <span class="token punctuation">&#123;</span> title<span class="token operator">:</span> <span class="token string">"home"</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre>
<p>实现一个配置文件合并:</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> config <span class="token operator">=</span> <span class="token punctuation">&#123;</span><span class="token operator">...</span>defaultConfig<span class="token punctuation">,</span> <span class="token operator">...</span>userConfig<span class="token punctuation">&#125;</span></code></pre>
<p>这种方式容易造成对象属性污染, 我们可以使用TS这样定义</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">interface</span> <span class="token class-name">IMerge</span> <span class="token punctuation">&#123;</span>
  <span class="token operator">&lt;</span><span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token class-name">Record<span class="token operator">&lt;</span><span class="token builtin">string</span><span class="token punctuation">,</span> <span class="token builtin">any</span><span class="token operator">></span></span><span class="token operator">></span><span class="token punctuation">(</span>sourceObj<span class="token operator">:</span> Partial<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">,</span> targetObj<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span><span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre></li>
<li><p>定义函数的返回值</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token comment">// 接受一个函数, 返回Promise</span>
<span class="token keyword">function</span> <span class="token function">delayCall</span><span class="token punctuation">(</span><span class="token parameter">func</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
    <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token keyword">const</span> result <span class="token operator">=</span> <span class="token function">func</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token function">resolve</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span> <span class="token number">1000</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<p>定义类型</p>
<pre class="language-typescript" data-language="typescript"><code class="language-typescript"><span class="token keyword">type</span> <span class="token class-name">IdelayCall</span> <span class="token operator">=</span> <span class="token operator">&lt;</span><span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token builtin">any</span><span class="token operator">></span><span class="token punctuation">(</span>func<span class="token operator">:</span> <span class="token constant">T</span><span class="token punctuation">)</span> <span class="token operator">=></span> ReturnType<span class="token operator">&lt;</span><span class="token constant">T</span><span class="token operator">></span><span class="token punctuation">;</span>
<span class="token keyword">type</span> <span class="token class-name">IReturnType<span class="token operator">&lt;</span><span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token punctuation">(</span><span class="token operator">...</span>args<span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">)</span> <span class="token operator">=></span></span> <span class="token builtin">any</span><span class="token operator">></span> <span class="token operator">=</span> <span class="token constant">T</span> <span class="token keyword">extends</span> <span class="token punctuation">(</span>
  <span class="token operator">...</span>args<span class="token operator">:</span> <span class="token builtin">any</span>
<span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token keyword">infer</span> <span class="token constant">R</span><span class="token operator">?</span> <span class="token constant">R</span><span class="token operator">:</span> <span class="token builtin">any</span><span class="token punctuation">;</span>

<span class="token comment">//关键字extends跟随泛型出现时, 表示类型推断, 其表达可类比三元表达式</span>
<span class="token comment">//如T===判断类型？类型A: 类型B</span>
<span class="token comment">//关键字[infer]出现在类型推荐中, 表示定义类型变量, 可以用于指代类型</span>
<span class="token comment">//如该场景下, 将函数的返回值类型作为变量, 使用新泛型R表示, 使用在类型推荐命中的结果中</span></code></pre></li>
</ul>
<h4 id="使用">使用</h4>
<ul>
<li>浏览器环境的webpackloader:
<ul>
<li>使用TSC引擎的loader: <a
target="_blank" rel="noopener" href="https://www.npmjs.com/package/awesome-typescript-loader">awesome-typescript-loader</a></li>
<li>使用Babel引擎的loader: <a
target="_blank" rel="noopener" href="https://www.npmjs.com/package/babel-loader">babel-loader</a></li>
</ul></li>
<li>Node: tsc</li>
</ul>
<h3 id="day8-2-小游戏开发---ycaptain">Day8-2 小游戏开发 - ycaptain</h3>
<p>游戏分类</p>
<table>
<colgroup>
<col style="width: 26%" />
<col style="width: 14%" />
<col style="width: 14%" />
<col style="width: 18%" />
<col style="width: 16%" />
<col style="width: 9%" />
</colgroup>
<thead>
<tr class="header">
<th>动作类(ACT)</th>
<th>冒险类(AvG)</th>
<th>模拟类</th>
<th>角色扮演类(RPG)</th>
<th>策略类(SLG)</th>
<th>其余分支</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>射击游戏</td>
<td>文字冒险游戏</td>
<td>模拟经营游戏</td>
<td>+动作</td>
<td>回合制战略游戏</td>
<td>音乐游戏</td>
</tr>
<tr class="even">
<td>格斗游戏</td>
<td>动作冒险游戏</td>
<td>模拟养成游戏</td>
<td>+模拟</td>
<td>回合制战术游戏</td>
<td>休闲游戏</td>
</tr>
<tr class="odd">
<td>动作冒险游戏</td>
<td>视觉小说</td>
<td>模拟沙盒游戏</td>
<td>+策略</td>
<td>即时战略游戏</td>
<td>体育游戏</td>
</tr>
<tr class="even">
<td>动作角色扮演游戏(ARPG)</td>
<td>解密冒险游戏</td>
<td></td>
<td>+冒险</td>
<td>即时战术游戏</td>
<td>竞速游戏</td>
</tr>
<tr class="odd">
<td>模拟动作游戏</td>
<td>恋爱冒险游戏</td>
<td></td>
<td></td>
<td></td>
<td></td>
</tr>
</tbody>
</table>
<h4 id="前端游戏开发">前端游戏开发</h4>
<p><strong>开发分工</strong></p>
<p>最少需要三个部分:</p>
<ul>
<li>策划(数值策划, 内容策划)</li>
<li>程序(前端/后端)</li>
<li>美术(原画, 2D/3D, 音效/动效)</li>
<li>其他(QA/运营/运维/市场)</li>
</ul>
<p><strong>开发链路</strong></p>
<ul>
<li>立项阶: 市场调研, 验证想法产出策划案</li>
<li>原型阶段: 确定游戏玩法与开发可行性, 产出Demo</li>
<li>Alpha阶段: 进行宏观设计, 剧情与角色设计, 音效与UI设计,
产出体验版本</li>
<li>Beta阶段: 无限测试, 迭代</li>
<li>运维阶段</li>
</ul>
<p><strong>游戏引擎</strong>: 从游戏中抽离公共组件</p>
<h4 id="常见引擎">常见引擎</h4>
<ul>
<li>The NVL Maker: 无需编码只需要准备剧本与素材就可以生成游戏</li>
<li>RPG Maker: 低代码生成RPG游戏</li>
</ul>
<p><strong>web游戏引擎的能力</strong></p>
<ul>
<li>预加载:游戏中往往存在大量的静态素材, 包括场景, 元素, 声音, 动画,
模型, 贴图等, 如果以原生JS进行请求, 并统筹请求时间和加载的时机,
将会非常麻烦. 游戏引擎中的预加载引擎将加载时机, 加载过程加以抽象,
解决加载编码中的效率问题.</li>
<li>展示与图层, 组合系统︰对于Web游戏编程而言,
往往选择Canvas或WebGL作为渲染方式(大家可以想想为什么不用DOM作为渲染方式?）.
而Canvas 和 WebGL作为底层的
API,接口非常基础,需要用大量的编码来编写简单的展示.
而且图形之间没有组合和图层, 很难处理元素组合和图层问题. 渲染引擎和图层,
组合系统应运而生.</li>
<li>动画系统:动画往往被分为缓动动画和逐帧动画, 这里讨论缓动动画系统.
缓动动画系统在原生JS中需要搭配帧渲染进行考量而进行书写,
代码量和思考量巨大, 抽象程度低．所以需要游戏引擎动画系统.</li>
<li>音效和声音系统:游戏相较于普通的Web前端而言需要更加立体, 及时的反馈,
声音和音效是反馈的重要组成部分. 所以声音和音效系统往往包含了声音的播放,
音量, 截止, 暂停等功能的集成.</li>
</ul>
<p><strong>常见引擎</strong></p>
<ul>
<li>Cocos</li>
<li>Laya</li>
<li>Egret</li>
<li>CreateJS</li>
<li>Phaser</li>
</ul>
<p><strong>浏览器渲染模式</strong></p>
<ul>
<li>保留模式: 渲染命令发送给浏览器API, 让浏览器API代为执行(DOM渲染)</li>
<li>快速模式: 渲染命令直接发给CPU, 要求CPU执行(Canvas渲染)</li>
</ul>
<h4 id="pixijsweb进行游戏开发">PixiJS+Web进行游戏开发</h4>
<p>PixiJS是一个2D渲染引擎, 很多尤其引擎都采用PixiJS进行渲染</p>
<p>基本流程</p>
<ul>
<li><p>创建一个矩形区域, 并指定大小</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> app <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PIXI<span class="token punctuation">.</span>Application</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span> <span class="token literal-property property">width</span><span class="token operator">:</span> <span class="token number">250</span><span class="token punctuation">,</span> <span class="token literal-property property">height</span><span class="token operator">:</span> <span class="token number">250</span> <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>将Canvas舞台添加到DOM</p>
<pre class="language-js" data-language="js"><code class="language-js">document<span class="token punctuation">.</span>body<span class="token punctuation">.</span><span class="token function">appendchild</span><span class="token punctuation">(</span>app<span class="token punctuation">.</span>view<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>此时PixiJS会自动判断是使用Canvas还是WebGL渲染, 默认采用的是WebGL,
也可以强制指定使用Canvas模式</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> app <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">PIXI<span class="token punctuation">.</span>Application</span><span class="token punctuation">(</span>
    <span class="token literal-property property">width</span><span class="token operator">:</span> <span class="token number">250</span><span class="token punctuation">,</span> 
    <span class="token literal-property property">height</span><span class="token operator">:</span> <span class="token number">250</span><span class="token punctuation">,</span> 
    <span class="token literal-property property">transparent</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span> 
    <span class="token literal-property property">forceCanvas</span><span class="token operator">:</span> <span class="token boolean">true</span> 
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre></li>
<li><p>向舞台中添加元素</p>
<ul>
<li><p>添加一张图片</p>
<p>在PixiJS中图片都被放置在Sprite容器中,
加载一张图片之前要先加载Sprite</p>
<p>Pixi使用纹理缓存来存储和引用Sprite所需要的纹理.
纹理的名称字符串就是图像的地址.
例如使用<code>PIXI.utils.TextureCache[“images/cat.png”]</code>存储图片,
然后使用<code>PIXI.loader</code>加载,
最后使用<code>app.stage.addChild(sprite)</code>加载图像</p>
<p>可以定义Sprite的属性</p>
<pre class="language-js" data-language="js"><code class="language-js">sprite<span class="token punctuation">.</span>width <span class="token operator">=</span> <span class="token number">80</span><span class="token punctuation">;</span> 
sprite<span class="token punctuation">.</span>height <span class="token operator">=</span> <span class="token number">120</span><span class="token punctuation">;</span>
sprite<span class="token punctuation">.</span>position<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token number">10</span><span class="token punctuation">,</span> <span class="token number">10</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
sprite<span class="token punctuation">.</span>scale<span class="token punctuation">.</span><span class="token function">set</span><span class="token punctuation">(</span><span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span> 
sprite<span class="token punctuation">.</span>rotation <span class="token operator">=</span><span class="token number">0.5</span><span class="token punctuation">;</span>

app<span class="token punctuation">.</span>tiker<span class="token punctuation">.</span><span class="token function">add</span><span class="token punctuation">(</span><span class="token parameter">delta</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>			<span class="token comment">// 每帧调用一次 </span>
    sprite<span class="token punctuation">.</span>x <span class="token operator">+=</span> <span class="token number">1</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre></li>
<li><p>...</p></li>
</ul></li>
</ul>
<h3 id="day9-1-小程序技术全解---张晓伟">Day9-1 小程序技术全解 -
张晓伟</h3>
<h4 id="小程序业务价值">小程序业务价值</h4>
<p><strong>与WEB相比</strong></p>
<ul>
<li>固定的语法与统一的版本管理, 平台可以更方便的进行审核</li>
<li>平台能够控制各个入口, 如二维码, 文章内嵌, 端内分享.
带来更好的用户体验</li>
<li>架构特殊, 流畅, 跳转体验优秀</li>
</ul>
<p><strong>小程序价值</strong></p>
<ul>
<li>渠道价值: 便捷, 依托于超级干台, 便于导流</li>
<li>业务探索价值: 开发难度和成本都低方便快速试错</li>
<li>数字升级价值: 有良好的容错空间. 线下使用范围广.</li>
</ul>
<h4 id="小程序原理">小程序原理</h4>
<ul>
<li><p>最朴素的实现方法: WebView + JSBridge</p>
<p>存在问题</p>
<ul>
<li>脱机工作</li>
<li>网页切换体验</li>
<li>无法保证安全</li>
</ul></li>
<li><p>希望小程序解决的问题</p>
<ul>
<li>开发门槛低(HTML+JS+CSS)</li>
<li>接近原生的使用体验(支持离线资源加载, 渲染,
通过构造多webview每次页面切换实质上是切换webview保证返回之前页面无需渲染)</li>
<li>保证安全(独立JS沙箱限制DOM操作)</li>
</ul></li>
<li><p>小程序架构</p>
<p>分为渲染层与逻辑层, 逻辑层中运行着JS, JS将页面数据传递给平台,
平台下放数据, 使用diff算法重新渲染包含webview的渲染层</p></li>
</ul>
<h4 id="小程序语法">小程序语法</h4>
<p>以字节小程序为例</p>
<ul>
<li>HTML -&gt; TTML(提供模板语法与指令)</li>
<li>CSS -&gt; TTSS(与css一样,
带来了新单位<code>rpx</code>表示页面宽度的<span
class="math inline">\(\frac{1}{750}\)</span>)</li>
<li>JS(使用配置对象描述页面传递属性)</li>
</ul>
<p>基于此尝试实现一个番茄时钟</p>
<p>index.ttml</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>view</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>container<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>view</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>clock<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
        &#123;&#123;timeText&#125;&#125;
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>view</span><span class="token punctuation">></span></span>
    <span class="token comment">&lt;!-- bindtap: 触碰后离开 --></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name"><span class="token namespace">tt:</span>if</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>&#123;&#123;running&#125;&#125;<span class="token punctuation">"</span></span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">bindtap</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onReset<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>重置<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
    <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>button</span> <span class="token attr-name"><span class="token namespace">tt:</span>else</span> <span class="token attr-name">class</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>btn<span class="token punctuation">"</span></span> <span class="token attr-name">bindtap</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>onStart<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>开始<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>button</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>view</span><span class="token punctuation">></span></span></code></pre>
<p>index.js</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> app <span class="token operator">=</span> <span class="token function">getApp</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token keyword">const</span> timeLength <span class="token operator">=</span> <span class="token number">25</span><span class="token operator">*</span><span class="token number">60</span>

<span class="token keyword">function</span> <span class="token function">getTime</span><span class="token punctuation">(</span><span class="token parameter">t</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> mm <span class="token operator">=</span> Math<span class="token punctuation">.</span><span class="token function">floor</span><span class="token punctuation">(</span>time<span class="token operator">/</span><span class="token number">60</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> ss <span class="token operator">=</span> time<span class="token operator">%</span><span class="token number">60</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> fmm <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">0</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>mm<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">const</span> fss <span class="token operator">=</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">0</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>ss<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span><span class="token punctuation">.</span><span class="token function">slice</span><span class="token punctuation">(</span><span class="token operator">-</span><span class="token number">2</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token keyword">return</span> <span class="token template-string"><span class="token template-punctuation string">`</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>fmm<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token string">:</span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">$&#123;</span>fss<span class="token interpolation-punctuation punctuation">&#125;</span></span><span class="token template-punctuation string">`</span></span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">let</span> timer <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> time <span class="token operator">=</span> timeLength<span class="token punctuation">;</span>

<span class="token function">Page</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
  <span class="token literal-property property">data</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
    <span class="token literal-property property">timeText</span><span class="token operator">:</span> <span class="token function">getTime</span><span class="token punctuation">(</span>time<span class="token punctuation">)</span><span class="token punctuation">,</span>
    <span class="token literal-property property">running</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token function">onStart</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setData</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span><span class="token literal-property property">running</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    timer <span class="token operator">=</span> <span class="token function">setInterval</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token operator">=></span><span class="token punctuation">&#123;</span>
      <span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">--</span>time <span class="token operator">===</span> <span class="token number">0</span><span class="token punctuation">)</span><span class="token keyword">return</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">onReset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setData</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
        <span class="token literal-property property">timeText</span><span class="token operator">:</span> <span class="token function">getTime</span><span class="token punctuation">(</span>time<span class="token punctuation">)</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span><span class="token number">1000</span><span class="token punctuation">)</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token function">onReset</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">&#123;</span>
    <span class="token function">clearInterval</span><span class="token punctuation">(</span>timer<span class="token punctuation">)</span><span class="token punctuation">;</span>
    timer<span class="token operator">=</span><span class="token keyword">null</span><span class="token punctuation">;</span>
    time <span class="token operator">=</span> timeLength<span class="token punctuation">;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">setData</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span>
      <span class="token literal-property property">timeText</span><span class="token operator">:</span> <span class="token function">getTime</span><span class="token punctuation">(</span>time<span class="token punctuation">)</span><span class="token punctuation">,</span>
      <span class="token literal-property property">running</span><span class="token operator">:</span> <span class="token boolean">false</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span></code></pre>
<p>index.ttss</p>
<pre class="language-css" data-language="css"><code class="language-css"><span class="token selector">.container</span> <span class="token punctuation">&#123;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 100vh<span class="token punctuation">;</span>
  <span class="token property">display</span><span class="token punctuation">:</span> flex<span class="token punctuation">;</span>
  <span class="token property">flex-direction</span><span class="token punctuation">:</span> column<span class="token punctuation">;</span>
  <span class="token property">justify-content</span><span class="token punctuation">:</span> space-between<span class="token punctuation">;</span>
  <span class="token property">align-items</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>
  <span class="token property">text-align</span><span class="token punctuation">:</span> center<span class="token punctuation">;</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> aqua<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">.clock</span><span class="token punctuation">&#123;</span>
  <span class="token property">width</span><span class="token punctuation">:</span> 400rpx<span class="token punctuation">;</span>
  <span class="token property">height</span><span class="token punctuation">:</span> 400rpx<span class="token punctuation">;</span>
  <span class="token property">border-radius</span><span class="token punctuation">:</span> 200rpx<span class="token punctuation">;</span>
  <span class="token property">border</span><span class="token punctuation">:</span> #fff solid 10rpx<span class="token punctuation">;</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 10vh auto<span class="token punctuation">;</span>
  <span class="token property">line-height</span><span class="token punctuation">:</span> 400rpx<span class="token punctuation">;</span>
  <span class="token property">font-size</span><span class="token punctuation">:</span> 100rpx<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span>

<span class="token selector">.btn</span><span class="token punctuation">&#123;</span>
  <span class="token property">margin</span><span class="token punctuation">:</span> 10vh auto<span class="token punctuation">;</span>
  <span class="token property">background-color</span><span class="token punctuation">:</span> #fff0<span class="token punctuation">;</span>
  <span class="token property">outline-color</span><span class="token punctuation">:</span> #fff<span class="token punctuation">;</span>
  <span class="token property">outline-style</span><span class="token punctuation">:</span> solid<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<h4 id="跨端架构">跨端架构</h4>
<p>解决问题:</p>
<ul>
<li>大型复杂项目的组件化开发</li>
<li>一次开发多端适配</li>
</ul>
<p>常见框架</p>
<table>
<thead>
<tr class="header">
<th></th>
<th>remax</th>
<th>taro</th>
<th>megalo</th>
<th>mpvue</th>
<th>uni-app</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>语法</td>
<td>react</td>
<td>React/Vue</td>
<td>Vue</td>
<td>Vue</td>
<td>Vue</td>
</tr>
<tr class="even">
<td>厂家</td>
<td>蚂蚁金服</td>
<td>京东</td>
<td>网易</td>
<td>美团</td>
<td>Hbuilder</td>
</tr>
</tbody>
</table>
<p>框架的运行原理: 转译, 分为编译时转义与运行时转译</p>
<ul>
<li><p>编译时</p>
<p>通过AST解析将代码解析到语法树, 重新组合生成小程序页面</p>
<p>缺点: 无法完全抹平差异</p></li>
<li><p>运行时</p>
<p>通过虚拟DOM与Template动态生成DOM</p>
<p>虚拟DOM与JS代码运行在逻辑层,
在刷新时将DOM树发到渲染层的组合template与实际要渲染的元素</p>
<p>缺点: 性能可能会稍差</p></li>
</ul>
<h3 id="day9-2-前端设计模式应用---吴立宁">Day9-2 前端设计模式应用 -
吴立宁</h3>
<p>设计模式: 软件设计中常见问题的解决方案模型</p>
<p>设计模式类型:</p>
<ul>
<li>创建型: 如何创建一个对象</li>
<li>结构型: 对象之间如何组装</li>
<li>行为型: 复杂对象之间的高效通信与职责划分</li>
</ul>
<h4
id="浏览器中的设计模式单例发布订阅">浏览器中的设计模式(单例&amp;发布订阅)</h4>
<p><strong>单例模式</strong></p>
<p>全局仅存在一个对象, 在任何地方创建的类的实例都是同一个对象,
在任何地方访问的都是同一个对象. 一般用于缓存, 全局状态管理</p>
<p>浏览器中的原生单例模式</p>
<pre class="language-js" data-language="js"><code class="language-js">window</code></pre>
<p>实现</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">SingletonClass</span> <span class="token punctuation">&#123;</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token comment">/* */</span><span class="token punctuation">&#125;</span>
  <span class="token keyword">static</span> instance <span class="token operator">=</span> <span class="token keyword">null</span><span class="token punctuation">;</span>
  <span class="token keyword">static</span> <span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">return</span> <span class="token punctuation">(</span><span class="token keyword">this</span><span class="token punctuation">.</span>instance <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span>instance <span class="token operator">||</span> <span class="token keyword">new</span> <span class="token class-name">SingletonClass</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">let</span> ins1 <span class="token operator">=</span> SingletonClass<span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">let</span> ins2 <span class="token operator">=</span> SingletonClass<span class="token punctuation">.</span><span class="token function">getInstance</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>SingletonClass<span class="token punctuation">.</span>cnt<span class="token punctuation">,</span> ins1 <span class="token operator">===</span> ins2<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p>由于JS是动态语言, 我们可以自由创建对象, 甚至不声明类,
因此我们可以将单例模式简化成一个函数,
将使用的变量作为使用最大作用域上</p>
<p><strong>发布订阅模式(观察者模式)</strong></p>
<p>一种订阅机制: 在订阅对象发生变化的时候通知订阅者</p>
<p>发布订阅模式可以用来做事件之间的订阅,
方便对象之间的解耦(厨师发布一道菜, 服务员来取)</p>
<p>浏览器中的原生订阅模式</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> btn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'btn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
btn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> funcToDoSth<span class="token punctuation">)</span><span class="token punctuation">;</span></code></pre>
<p><code>btn</code>就是一个订阅对象,
<code>funcToDoSth</code>是订阅者</p>
<p>实现</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">Publisher</span> <span class="token punctuation">&#123;</span>
  subscribers <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">]</span><span class="token punctuation">;</span>               <span class="token comment">// 存放订阅者信息</span>
  <span class="token function">subscribe</span><span class="token punctuation">(</span><span class="token parameter">subscriber<span class="token punctuation">,</span> action</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span> <span class="token comment">// 加入订阅</span>
    subscriber<span class="token punctuation">.</span><span class="token function">push</span><span class="token punctuation">(</span><span class="token punctuation">&#123;</span> subscriber<span class="token punctuation">,</span> action <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token function">foo</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>                         <span class="token comment">// 一个朴素的函数</span>
    <span class="token comment">// 做一些无关紧要的事情直到到达触发时机</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>subscribers<span class="token punctuation">.</span><span class="token function">forEach</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">&#123;</span> subscriber<span class="token punctuation">,</span> action <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
      <span class="token function">action</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span></code></pre>
<h4
id="js中的设计模式原型代理模式">JS中的设计模式(原型&amp;代理模式)</h4>
<p><strong>原型模式</strong></p>
<p>通过复制已有的对象创建新对象,
实际上JS中使用原型对象创建对象就是基于这种模式</p>
<p>使用JS的<code>Object.create</code>API实现</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> baseUser <span class="token operator">=</span> <span class="token punctuation">&#123;</span>
  <span class="token literal-property property">attrbute1</span><span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
  <span class="token literal-property property">attrbute2</span><span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
  <span class="token literal-property property">attrbute3</span><span class="token operator">:</span> <span class="token string">''</span><span class="token punctuation">,</span>
  <span class="token function">function1</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token function">function2</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
  <span class="token function">function3</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>

<span class="token keyword">const</span> <span class="token function-variable function">createBaseUser</span> <span class="token operator">=</span> <span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">&#123;</span> attrbute1<span class="token punctuation">,</span> attrbute2<span class="token punctuation">,</span> attrbute3 <span class="token punctuation">&#125;</span></span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">const</span> res <span class="token operator">=</span> Object<span class="token punctuation">.</span><span class="token function">create</span><span class="token punctuation">(</span>baseUser<span class="token punctuation">)</span><span class="token punctuation">;</span>
  res<span class="token punctuation">.</span>attrbute1 <span class="token operator">=</span> attrbute1<span class="token punctuation">;</span>
  res<span class="token punctuation">.</span>attrbute2 <span class="token operator">=</span> attrbute2<span class="token punctuation">;</span>
  res<span class="token punctuation">.</span>attrbute3 <span class="token operator">=</span> attrbute3<span class="token punctuation">;</span>
  <span class="token keyword">return</span> res<span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
</code></pre>
<p>不使用API就使用深拷贝实现</p>
<p><strong>代理模式</strong></p>
<p>可以自定义对对象的访问方式, 允许在访问修改对象前后进行额外处理.
一般用于监控代理工具, 前端框架实现</p>
<p>使用JS中Proxy的set, get实现</p>
<p><strong>迭代器模式</strong></p>
<p>在不暴露数据类型的情况下访问集合中的数据, 一般用于列表,
数组等数据类型</p>
<p>可以使用JS中的API<code>for of</code>迭代,
JS中默认提供了可迭代的数据类型,
我们可以通过为对象加入<code>[Symbol.iterator]</code>
方法使对象变为可迭代的</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">class</span> <span class="token class-name">IteratorClass</span> <span class="token punctuation">&#123;</span>
  <span class="token function">constructor</span><span class="token punctuation">(</span><span class="token parameter">arr</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">this</span><span class="token punctuation">.</span>arr <span class="token operator">=</span> arr<span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
  <span class="token punctuation">[</span>Symbol<span class="token punctuation">.</span>iterator<span class="token punctuation">]</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token keyword">let</span> idx <span class="token operator">=</span> <span class="token operator">-</span><span class="token number">1</span><span class="token punctuation">;</span>
    <span class="token keyword">return</span> <span class="token punctuation">&#123;</span>
      <span class="token function-variable function">next</span><span class="token operator">:</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">&#123;</span>
        <span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token operator">++</span>idx <span class="token operator">===</span> <span class="token keyword">this</span><span class="token punctuation">.</span>arr<span class="token punctuation">.</span>length<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token punctuation">&#123;</span> <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token keyword">null</span><span class="token punctuation">,</span> <span class="token literal-property property">done</span><span class="token operator">:</span> <span class="token boolean">true</span> <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
        <span class="token keyword">return</span> <span class="token punctuation">&#123;</span>
          <span class="token literal-property property">value</span><span class="token operator">:</span> <span class="token keyword">this</span><span class="token punctuation">.</span>arr<span class="token punctuation">[</span>idx<span class="token punctuation">]</span><span class="token punctuation">,</span>
          <span class="token literal-property property">done</span><span class="token operator">:</span> <span class="token boolean">false</span><span class="token punctuation">,</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
      <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span>
<span class="token punctuation">&#125;</span>

<span class="token keyword">const</span> demo <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">IteratorClass</span><span class="token punctuation">(</span><span class="token punctuation">[</span><span class="token number">5</span><span class="token punctuation">,</span> <span class="token number">4</span><span class="token punctuation">,</span> <span class="token number">3</span><span class="token punctuation">,</span> <span class="token number">2</span><span class="token punctuation">,</span> <span class="token number">1</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">for</span> <span class="token punctuation">(</span><span class="token keyword">let</span> t <span class="token keyword">of</span> demo<span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>t<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span></code></pre>
<h4
id="前端框架中的设计模式代理组合模式">前端框架中的设计模式(代理&amp;组合模式)</h4>
<p><strong>代理模式</strong></p>
<p>与基于JS中<code>Proxy</code>API的代理模式模式不同</p>
<p>在前端框架中实现的MVVM的原理就是: JS代理了DOM元素,
在DOM事件触发后框架会拦截事件触发虚拟DOM的变化, 最终更新结果到DOM</p>
<p><strong>组合模式</strong></p>
<p>允许多个对象组合使用也可以单个使用</p>
<p>这种思想在组件化中使用</p>
<h4 id="总结">总结</h4>
<ul>
<li>设计模式不是万能的, 也很难将实际场景抽象为设计模式</li>
<li>现代语言中的优秀API使得我们可能无需严格按照标准设计模式实现</li>
<li>避免过度设计</li>
</ul>
<p>最后记一下<code>for in</code>与<code>for of</code></p>
<ul>
<li><p><code>for...in</code>是ES5的标准,
该方法遍历的是对象的属性名称(key: 键名). 一个Array对象也是一个对象,
数组中的每个元素的索引被视为属性名称, 所以在使用for...in遍历Array时,
拿到的是每个元素索引</p>
<blockquote>
<ul>
<li>一般用于遍历对象自身的和继承的可枚举属性.
以及对象从构造函数原型中继承的属性. 对于每个不同的属性,
语句都会被执行.</li>
<li>不建议使用<code>for in</code>遍历数组,
因为输出的顺序是不固定的.</li>
<li>如果迭代的对象的变量值是<code>null</code>或者<code>undefined</code>,
<code>for in</code>不执行循环体, 建议在使用<code>for in</code>循环之前,
先检查该对象的值是不是<code>null</code>或者<code>undefined</code></li>
<li><code>for…in</code>语句以原始插入顺序迭代对象的可枚举属性(只能迭代出可枚举的属性,
可枚举属性(JS自定义属性)/不可枚举属性(对象的内置属性, 如数组的length
就是一个内置属性, 所以for…in遍历不出来)).</li>
<li>for…in的原理是: Object.keys():
返回给定对象所有可枚举属性的字符串数组</li>
</ul>
</blockquote></li>
<li><p><code>for...of</code>是ES6的标准,
该方法遍历的是对象的属性所对应的值(value: 键值).
所以它用来遍历数组时得到每个元素的值</p>
<blockquote>
<ul>
<li><code>for…of</code> 语句在可迭代对象（包括 Array, Map, Set, String,
TypedArray, arguments 对象等等)上创建一个迭代循环, 调用自定义迭代钩子,
并为每个不同属性的值执行语句</li>
<li><code>for…of</code>语句遍历可迭代对象定义要迭代的数据（非自定义属性）</li>
<li><code>for…of</code>循环可以使用的范围包括Array, Set 和 Map 结构,
某些类似数组的对象, Generator 对象, 以及字符串.</li>
</ul>
</blockquote></li>
</ul>
<h3 id="day10-1-web多媒体入门---刘立国">Day10-1 Web多媒体入门 -
刘立国</h3>
<p><strong>发展</strong></p>
<ul>
<li>Flash/ActiveX/serveLite</li>
<li>HTML5的<code>video</code>等标签,
但是这些标签支持的格式与实现的功能实在是弱鸡,
我们也无法参与到多媒体数据的请求处理, 错误处理过程</li>
<li><a
target="_blank" rel="noopener" href="https://developer.mozilla.org/zh-CN/docs/Web/API/Media_Source_Extensions_API">Media
Source Extensions API</a>: 为了解决H5标签过于封闭的问题, 媒体源扩展
API提供了实现无插件且基于 Web 的流媒体的功能</li>
</ul>
<h4 id="编码格式">编码格式</h4>
<ul>
<li><p>图像基本概念</p>
<ul>
<li>图像分辨率: 用于确定组成一副图像的像素数据,
就是指在水平和垂直方向上图像所具有的像素个数.</li>
<li>图像深度: 图像深度是指存储每个像素所需要的位数.
图像深度决定了图像的每个像素可能的颜色数, 或可能的灰度级数.</li>
</ul></li>
<li><p>视频基本概念</p>
<ul>
<li>分辨率: 每一帧的图像分辨率</li>
<li>帧率: 视频单位时间内包含的视频帧的数量</li>
<li>码率: 就是指视频单位时间内传输的数据量, 一般我们用kbps来表示,
即千位每秒.</li>
</ul></li>
<li><p>视频帧: 分为I帧, P帧, B帧</p>
<ul>
<li>I帧: I帧又称帧内编码帧, 是一种自带全部信息的独立帧,
无需参考其他帧便可独立进行解码</li>
<li>P帧: P帧又称前向预测编码帧,
需要参考前面的I帧或者P帧才能进行编码</li>
<li>B帧: B帧又称双向预测编码帧, B帧需要参考前后的I帧或者P帧才能进行编码,
记录的是本帧与前后帧的差别</li>
</ul></li>
<li><p>DTS与PTS</p>
<ul>
<li>DTS: 即解码时间戳,
这个时间戳的意义在于告诉播放器该在什么时候解码这一帧的数据.</li>
<li>PTS: 即显示时间戳,
这个时间戳用来告诉播放器该在什么时候显示这一帧的数据.</li>
</ul>
<p>当视频流中没有 B 帧时, 通常 DTS 和 PTS 的顺序是一致的. 但如果有 B
帧时, 解码顺序和播放顺序不一致了.</p>
<p>一个视频中, 帧的显示顺序是: I B B P, 现在我们需要在解码 B 帧时知道 P
帧中信息, 因此这几帧在视频流中的顺序可能是: I P B B,
这时候就体现出每帧都有 DTS 和 PTS 的作用了. DTS
告诉我们该按什么顺序解码这几帧图像, PTS
告诉我们该按什么顺序显示这几帧图像. 顺序大概如下:</p>
<pre class="language-none"><code class="language-none">   PTS: 1 2 3 4 
   DTS: 1 3 4 2 
Stream: I B B P </code></pre></li>
<li><p>GOP(Group of Picture, 一组图片)</p>
<p>表示两个I帧之间的间隔, GOP越小代表视频越大, GOP不能很大,
否则当用户跳转到指定帧的时候就需要从很远的I帧开始计算</p></li>
</ul>
<p><strong>为什么要编码</strong>: 压缩体积, 方便存储与传输</p>
<p><strong>编码的本质</strong>: 压缩冗余数据</p>
<ul>
<li>空间冗余: 图片中有很多连续的相同像素点</li>
<li>时间冗余: 相邻两帧之间有相同位置相同值的像素</li>
<li>编码冗余: 图片中仅仅使用了很少种类的颜色,
我们将24Bit的颜色表示进行重新编码</li>
<li>视觉冗余: 人眼对于高频数据不敏感</li>
</ul>
<p><strong>编码处理流程</strong></p>
<ul>
<li>预测: 帧内预测与帧间预测, 分别去除空间冗余与时间冗余</li>
<li>变换: 去除空间冗余(将帧进行重新排列)</li>
<li>量化: 去除视觉冗余</li>
<li>熵编码: 去除熵冗余</li>
</ul>
<p><strong>常见编码格式</strong></p>
<ul>
<li><code>h.262</code>: 数字电视, 光盘</li>
<li><code>h.264</code>: PC端视频</li>
<li><code>h.265</code>: PC端高分辨率视频</li>
<li><code>h.266</code>: VR</li>
<li><code>VP9</code>与<code>VP10</code>: <code>h.265</code>借鉴版,
谷歌出品</li>
<li><code>AV1</code>: AOM开放媒体联盟(亚马逊, 微软, google, 思科,
英特尔)联合出品, 比肩<code>h.265</code></li>
<li><code>AVS</code>: 国产编码</li>
</ul>
<h4 id="封装格式">封装格式</h4>
<p>封装格式: 存储音视频, 图片, 字幕信息的容器</p>
<table>
<colgroup>
<col style="width: 71%" />
<col style="width: 28%" />
</colgroup>
<thead>
<tr class="header">
<th>视频封装格式</th>
<th>视频文件格式</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>AVI(Audio Video Interleave)</td>
<td>AVI</td>
</tr>
<tr class="even">
<td>WMV(Windows Media Video)</td>
<td>WMV</td>
</tr>
<tr class="odd">
<td>MPEG(Moving Picture Experts Group)分为MPEG-1, MPEG-2, MPEG-4</td>
<td>MPG MPEG VOB DAT 3GP MP4</td>
</tr>
<tr class="even">
<td>Matroska</td>
<td>MKV</td>
</tr>
<tr class="odd">
<td>Real Video</td>
<td>RM RMVB</td>
</tr>
<tr class="even">
<td>QuickTime File Format</td>
<td>MOV</td>
</tr>
<tr class="odd">
<td>Flash Video</td>
<td>FLV</td>
</tr>
</tbody>
</table>
<h4 id="多媒体元素和扩展api">多媒体元素和扩展API</h4>
<ul>
<li><p><code>&lt;video&gt;&lt;/video&gt;</code>标签</p>
<pre class="language-html" data-language="html"><code class="language-html"><span class="token comment">&lt;!--方式1--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>video</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myVideo.mp4<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>video</span><span class="token punctuation">></span></span>

<span class="token comment">&lt;!--方式2--></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>video</span> <span class="token attr-name">controls</span><span class="token punctuation">></span></span>
  <span class="token comment">&lt;!--使用source可以指定多个源, 浏览器自上向下尝试--></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myVideo.mp4<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>video/mp4<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>source</span> <span class="token attr-name">src</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myVideo.webm<span class="token punctuation">"</span></span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>video/webm<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
  <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>p</span><span class="token punctuation">></span></span>Your browser doesn't support HTML5 video. Here is
     a <span class="token tag"><span class="token tag"><span class="token punctuation">&lt;</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation attr-equals">=</span><span class="token punctuation">"</span>myVideo.mp4<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>link to the video<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>a</span><span class="token punctuation">></span></span> instead.<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>p</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation">&lt;/</span>video</span><span class="token punctuation">></span></span></code></pre></li>
<li><p><code>&lt;audio&gt;&lt;/audio&gt;</code>:
播放音频与<code>&lt;video&gt;&lt;/video&gt;</code>类似</p></li>
<li><p><code>&lt;video&gt;</code>与<code>&lt;audio&gt;</code>的公共方法</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">const</span> ele <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">'audio'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
ele<span class="token punctuation">.</span><span class="token function">play</span><span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token comment">// ...</span></code></pre>
<table>
<thead>
<tr class="header">
<th>方法</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>play()</td>
<td>开始播放音频/视频<strong>(异步执行)</strong></td>
</tr>
<tr class="even">
<td>pause()</td>
<td>暂停当前播放的音频/视频</td>
</tr>
<tr class="odd">
<td>load()</td>
<td>重新加载音频/视频元素</td>
</tr>
<tr class="even">
<td>canPlayType()</td>
<td>检测浏览器是否能播放指定的音频/视频类型</td>
</tr>
<tr class="odd">
<td>addTextTrack()</td>
<td>向音频/视频添加新的文本轨道</td>
</tr>
</tbody>
</table>
<p><code>&lt;video&gt;</code>与<code>&lt;audio&gt;</code>的公共属性</p>
<table>
<thead>
<tr class="header">
<th>属性</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>autoplay</td>
<td>设置或返回是否在加载完成后随即播放音频/视频</td>
</tr>
<tr class="even">
<td>controls</td>
<td>设置或返回音频/视频是否显示控制条(比如播放/暂停等)</td>
</tr>
<tr class="odd">
<td>currentTime</td>
<td>设置或返回音频/视频中的当前播放位置(以秒计)</td>
</tr>
<tr class="even">
<td>duration</td>
<td>返回当前音频/视频的长度(以秒计)</td>
</tr>
<tr class="odd">
<td>src</td>
<td>设置或返回音频/视频元素的当前来源</td>
</tr>
<tr class="even">
<td>volume</td>
<td>设置或返回音频/视频的音量</td>
</tr>
<tr class="odd">
<td>buffered</td>
<td>返回表示音频/视频已缓冲部分的TimeRanges对象</td>
</tr>
<tr class="even">
<td>playbackRate</td>
<td>设置或返回音频/视频播放的速度.</td>
</tr>
<tr class="odd">
<td>]error</td>
<td>返回表示音频/视频错误状态的MediaError对象</td>
</tr>
<tr class="even">
<td>readyState</td>
<td>返回音频/视频当前的就绪状态.</td>
</tr>
</tbody>
</table>
<p><code>&lt;video&gt;</code>与<code>&lt;audio&gt;</code>的公共事件</p>
<table>
<colgroup>
<col style="width: 18%" />
<col style="width: 81%" />
</colgroup>
<thead>
<tr class="header">
<th>事件</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>loadedmetadata</td>
<td>当浏览器已加载音频/视频的元数据时触发</td>
</tr>
<tr class="even">
<td>canplay</td>
<td>当浏览器可以开始播放音频/视频时触发</td>
</tr>
<tr class="odd">
<td>play</td>
<td>当音频/视频已开始或不再暂停时触发(指的是开始播放,
但不一定真正开始了, 比如正在缓存)</td>
</tr>
<tr class="even">
<td>playing</td>
<td>当音频/视频在因缓冲而暂停或停止后已就绪时触发(指的是真正开始了)</td>
</tr>
<tr class="odd">
<td>pause</td>
<td>当音频/视频已暂停时触发</td>
</tr>
<tr class="even">
<td>timeupdate</td>
<td>当目前的播放位置已更改时触发</td>
</tr>
<tr class="odd">
<td>seeking</td>
<td>当用户开始移动/跳跃到音频/视频中的新位置时触发(触发前)</td>
</tr>
<tr class="even">
<td>seeked</td>
<td>当用户已移动/跳跃到音频/视频中的新位置时触发(触发后)</td>
</tr>
<tr class="odd">
<td>waiting</td>
<td>当视频由于需要缓冲下一帧而停止时触发</td>
</tr>
<tr class="even">
<td>ended</td>
<td>当目前的播放列表已结束时触发</td>
</tr>
</tbody>
</table>
<p><code>&lt;video&gt;</code>与<code>&lt;audio&gt;</code>的缺陷</p>
<ul>
<li>不能播放HLS, FLV文件</li>
<li>无法参与请求控制（无法分段, 无法无缝切换清晰度,
无法准确预加载）</li>
</ul></li>
<li><p>MSE</p>
<ul>
<li>指出无插件在Web端播放流媒体文件</li>
<li>支持更多文件格式</li>
<li>支持参与请求控制（分段, 无缝切换清晰度, 准确预加载）</li>
<li><strong>IOS上的Safari不支持MSE</strong></li>
</ul></li>
<li><p>MSE的使用</p>
<pre class="language-js" data-language="js"><code class="language-js"><span class="token keyword">let</span> mimeCodec <span class="token operator">=</span> <span class="token string">'video/mp4; codecs="avc1.42E01E, mp4a.40.2"'</span><span class="token punctuation">;</span>
<span class="token comment">// 1. 创建Mediasource实例</span>
<span class="token keyword">let</span> mediasource <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">MediaSource</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 2. 指定Mediasource的URL</span>
video<span class="token punctuation">.</span>src <span class="token operator">=</span> <span class="token constant">URL</span><span class="token punctuation">.</span><span class="token function">createObiectURL</span><span class="token punctuation">(</span>mediaSource<span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token comment">// 3. 监听sourceopen</span>
mediasource<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'sourceopen'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> mediasource <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">;</span>
  <span class="token comment">// 4. 创建Buffer</span>
  <span class="token keyword">let</span> sourceBuffer <span class="token operator">=</span> mediaSource<span class="token punctuation">.</span><span class="token function">addSourceBuffer</span><span class="token punctuation">(</span>mimeCodec<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token comment">// 5. 添加数据,读取数据, 由于数据加载是异步的,我们还需要设置加载结束后监听</span>
  <span class="token function">fetchAB</span><span class="token punctuation">(</span><span class="token string">'frag_bunny.mp4'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token parameter">buf</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token comment">// 6. 创建updateend监听</span>
    sourceBuffer<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'updateend'</span><span class="token punctuation">,</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
      mediasource<span class="token punctuation">.</span><span class="token function">endOfStream</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
      video<span class="token punctuation">.</span><span class="token function">play</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
    sourceBuffer<span class="token punctuation">.</span><span class="token function">appendBuffer</span><span class="token punctuation">(</span>buf<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">)</span><span class="token punctuation">;</span>

<span class="token keyword">function</span> <span class="token function">fetchAB</span><span class="token punctuation">(</span><span class="token parameter">url<span class="token punctuation">,</span> cb</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
  <span class="token keyword">let</span> xhr <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">;</span>
  xhr<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token string">'get'</span><span class="token punctuation">,</span> url<span class="token punctuation">)</span><span class="token punctuation">;</span>
  xhr<span class="token punctuation">.</span>responseType <span class="token operator">=</span> <span class="token string">'arraybuffer'</span><span class="token punctuation">;</span>
  xhr<span class="token punctuation">.</span><span class="token function-variable function">onload</span> <span class="token operator">=</span> <span class="token keyword">function</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">&#123;</span>
    <span class="token function">cb</span><span class="token punctuation">(</span>xhr<span class="token punctuation">.</span>response<span class="token punctuation">)</span><span class="token punctuation">;</span>
  <span class="token punctuation">&#125;</span><span class="token punctuation">;</span>
  xhr<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">&#125;</span><span class="token punctuation">;</span></code></pre></li>
<li><p>MSE播放流程</p>
<figure>
<img data-src="./MSE-follow.jpg" alt="MSE播放流程" />
<figcaption aria-hidden="true">MSE播放流程</figcaption>
</figure>
<p>两种加载策略: 1.
将音视频加载到一个SourceBuffer然后再在HTML标签中分装到不同Track
Buffer.(最左边蓝色部分) 2. 直接用两个Buffer收数据(最右边两个部分)</p>
<ul>
<li>数据加载: 一般采用ts/flv/mp4封装格式</li>
<li>解封装: 获取视频流与音频流</li>
<li>重封装: MSE只支持fmp4格式(和mp4不同哈), 所以需要重新分装</li>
<li>加入Buffer</li>
<li>解码渲染</li>
<li>音视频同步</li>
</ul></li>
</ul>
<h4 id="常见流媒体协议">常见流媒体协议</h4>
<table>
<thead>
<tr class="header">
<th>协议名称</th>
<th>传输协议</th>
<th>封装格式</th>
<th>HTML5</th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>HLS</td>
<td>HTTP</td>
<td>M3U8/TS</td>
<td>支持</td>
</tr>
<tr class="even">
<td>HTTP-FLV</td>
<td>HTTP</td>
<td>FLV</td>
<td>支持</td>
</tr>
<tr class="odd">
<td>Dash</td>
<td>HTTP</td>
<td>FMP4</td>
<td>支持</td>
</tr>
<tr class="even">
<td>RTMP</td>
<td>TCP</td>
<td>FLV</td>
<td>不支持(也不怎么用)</td>
</tr>
</tbody>
</table>
<p>HLS是苹果提出的流媒体传输协议. 在服务端将视频编码为fmp4并分片,
分片后传输, 在请求的时候携带一个分片列表</p>
<h4 id="应用场景">应用场景</h4>
<ul>
<li>点播: 上传-转码-CDN分发</li>
<li>直播: 和点播差不多</li>
<li>图片: 重点在新格式的应用, 例如AVF, HEIF(基于H.265编码的图片)</li>
<li>云游戏: 客户端发布命令-后端传回图像</li>
<li>实时通讯: 视频会议等</li>
<li>线上视频编辑</li>
</ul>
<p><strong>新技术标准</strong></p>
<ul>
<li>WASM</li>
<li>WebCodecs: 前端音视频编解码</li>
<li>WebGPU: WebGL2代</li>
<li>WebVR, WebXR</li>
</ul>
<h3 id="day10-2-数据可视化基础---何菲菲">Day10-2 数据可视化基础 -
何菲菲</h3>
<p>类型:</p>
<ul>
<li>科学可视化: 实验数据可视化</li>
<li>信息可视化: 抽象数据可视化</li>
<li>可视化分析: 数据分析结果可视化</li>
</ul>
<h4 id="可视化的原则与常见错误">可视化的原则与常见错误</h4>
<p><strong>要求</strong></p>
<ul>
<li>正确的表达数据, 不产生歧义</li>
<li>如果数据是由视觉元素表示的,
那么元素应与感知程度成正比(透视失真)</li>
<li>图形的每一部分都应该保持连贯与一致(刻度盘)</li>
<li>补全数据上下文</li>
</ul>
<p><strong>原则</strong></p>
<ul>
<li>准确展示数据</li>
<li>节省笔墨</li>
<li>节省空间</li>
<li>消除不必要的无价值图形</li>
<li>最短时间传达最多的信息</li>
</ul>
<p><strong>数据墨水占比</strong></p>
<ul>
<li>可视化由墨水与空白区构成</li>
<li>数据墨水: 图形中表达信息的, 不可擦除的部分</li>
<li>我们应该尽量提高数据墨水占比</li>
</ul>
<h4 id="可视化评价模型">可视化评价模型</h4>
<p><strong>视觉感知</strong></p>
<p>可视化致力于利用大脑以外的资源增强大脑获取信息的能力</p>
<ul>
<li>利用相对判断与视觉假象(人类的视觉系统是相对变化的)</li>
<li>格式塔理论与构造学派</li>
</ul>
<p><strong>数据编码</strong>:
将数据信息(Key-Value)映射成可视化元素(可视化元素(点线面)+视觉通道(大小,
灰度, 颜色, 形状... ))的技术</p>
<ul>
<li>可视化符号
<ul>
<li>表示元素: 点线面</li>
<li>表示关系: 闭包, 连线</li>
</ul></li>
<li>视觉通道
<ul>
<li>数量通道: 位置, 长度, 角度, 面积, 深度, 色温, 饱和度, 曲率,
体积</li>
<li>标识通道: 空间区域, 色向, 动向, 形状</li>
</ul></li>
</ul>
<p><strong>p.s. 格式塔理论</strong></p>
<ul>
<li>就近原则(人们倾向于将距离上相近的元素归为一组) =&gt;
将我们希望突出关联性的元素放的近一点</li>
<li>相似原则(人们倾向于将形状大小颜色等相似的元素看作是一个整体)</li>
<li>连续性原则(人们倾向于按照事物的边界将不连续的对象补充为连续对象)</li>
<li>闭合原则(人们倾向于关注不完整/不闭合的图形中有闭合倾向的主体)</li>
<li>共势原则(人们强项于关注一个对象中有共同运动方向的一部分)</li>
<li>对称性原则(对称的元素通常会被视作一部分)</li>
<li>图形与背景关系原则(人们倾向于将小的, 凸面元素认为为图形, 将大的,
凹面的元素认为是背景)</li>
</ul>
<h4 id="可视化工具">可视化工具</h4>
<ul>
<li><p>D3</p></li>
<li><p>Vega: 一种图形语法, 通过JSON声明式的描述可视化</p>
<p>例如绘制一个柱状图</p>
<pre class="language-json" data-language="json"><code class="language-json"><span class="token punctuation">&#123;</span>
  <span class="token property">"$schema"</span><span class="token operator">:</span> <span class="token string">"https://vega.github.io/schema/vega/v5.json"</span><span class="token punctuation">,</span>
  <span class="token property">"description"</span><span class="token operator">:</span> <span class="token string">"A basic bar chart example, with value labels shown upon mouse hover."</span><span class="token punctuation">,</span>
  <span class="token property">"width"</span><span class="token operator">:</span> <span class="token number">400</span><span class="token punctuation">,</span>
  <span class="token property">"height"</span><span class="token operator">:</span> <span class="token number">200</span><span class="token punctuation">,</span>
  <span class="token property">"padding"</span><span class="token operator">:</span> <span class="token number">5</span><span class="token punctuation">,</span>

  <span class="token property">"data"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">&#123;</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"table"</span><span class="token punctuation">,</span>
      <span class="token property">"values"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">&#123;</span><span class="token property">"category"</span><span class="token operator">:</span> <span class="token string">"A"</span><span class="token punctuation">,</span> <span class="token property">"amount"</span><span class="token operator">:</span> <span class="token number">28</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>			<span class="token comment">// KV组合</span>
      <span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>

  <span class="token property">"signals"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">&#123;</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"tooltip"</span><span class="token punctuation">,</span>
      <span class="token property">"value"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token property">"on"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
        <span class="token punctuation">&#123;</span><span class="token property">"events"</span><span class="token operator">:</span> <span class="token string">"rect:mouseover"</span><span class="token punctuation">,</span> <span class="token property">"update"</span><span class="token operator">:</span> <span class="token string">"datum"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>	<span class="token comment">// 事件</span>
        <span class="token punctuation">&#123;</span><span class="token property">"events"</span><span class="token operator">:</span> <span class="token string">"rect:mouseout"</span><span class="token punctuation">,</span>  <span class="token property">"update"</span><span class="token operator">:</span> <span class="token string">"&#123;&#125;"</span><span class="token punctuation">&#125;</span>
      <span class="token punctuation">]</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>

  <span class="token property">"scales"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
    <span class="token punctuation">&#123;</span>														<span class="token comment">// 定义坐标轴</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"xscale"</span><span class="token punctuation">,</span>
      <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"band"</span><span class="token punctuation">,</span>
      <span class="token property">"domain"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"data"</span><span class="token operator">:</span> <span class="token string">"table"</span><span class="token punctuation">,</span> <span class="token property">"field"</span><span class="token operator">:</span> <span class="token string">"category"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token property">"range"</span><span class="token operator">:</span> <span class="token string">"width"</span><span class="token punctuation">,</span>
      <span class="token property">"padding"</span><span class="token operator">:</span> <span class="token number">0.05</span><span class="token punctuation">,</span>
      <span class="token property">"round"</span><span class="token operator">:</span> <span class="token boolean">true</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#123;</span>
      <span class="token property">"name"</span><span class="token operator">:</span> <span class="token string">"yscale"</span><span class="token punctuation">,</span>
      <span class="token property">"domain"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"data"</span><span class="token operator">:</span> <span class="token string">"table"</span><span class="token punctuation">,</span> <span class="token property">"field"</span><span class="token operator">:</span> <span class="token string">"amount"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token property">"nice"</span><span class="token operator">:</span> <span class="token boolean">true</span><span class="token punctuation">,</span>
      <span class="token property">"range"</span><span class="token operator">:</span> <span class="token string">"height"</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>

  <span class="token property">"axes"</span><span class="token operator">:</span> <span class="token punctuation">[</span>													<span class="token comment">// 定义坐标轴位置</span>
    <span class="token punctuation">&#123;</span> <span class="token property">"orient"</span><span class="token operator">:</span> <span class="token string">"bottom"</span><span class="token punctuation">,</span> <span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"xscale"</span> <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#123;</span> <span class="token property">"orient"</span><span class="token operator">:</span> <span class="token string">"left"</span><span class="token punctuation">,</span> <span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"yscale"</span> <span class="token punctuation">&#125;</span>
  <span class="token punctuation">]</span><span class="token punctuation">,</span>

  <span class="token property">"marks"</span><span class="token operator">:</span> <span class="token punctuation">[</span>												<span class="token comment">// 定义图形与动作</span>
    <span class="token punctuation">&#123;</span>
      <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"rect"</span><span class="token punctuation">,</span>
      <span class="token property">"from"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"data"</span><span class="token operator">:</span><span class="token string">"table"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
      <span class="token property">"encode"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token property">"enter"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
          <span class="token property">"x"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"xscale"</span><span class="token punctuation">,</span> <span class="token property">"field"</span><span class="token operator">:</span> <span class="token string">"category"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"width"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"xscale"</span><span class="token punctuation">,</span> <span class="token property">"band"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"y"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"yscale"</span><span class="token punctuation">,</span> <span class="token property">"field"</span><span class="token operator">:</span> <span class="token string">"amount"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"y2"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"yscale"</span><span class="token punctuation">,</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token property">"update"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
          <span class="token property">"fill"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"steelblue"</span><span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token property">"hover"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
          <span class="token property">"fill"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"red"</span><span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span>
      <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
    <span class="token punctuation">&#123;</span>
      <span class="token property">"type"</span><span class="token operator">:</span> <span class="token string">"text"</span><span class="token punctuation">,</span>
      <span class="token property">"encode"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
        <span class="token property">"enter"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
          <span class="token property">"align"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"center"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"baseline"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"bottom"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"fill"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"value"</span><span class="token operator">:</span> <span class="token string">"#333"</span><span class="token punctuation">&#125;</span>
        <span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
        <span class="token property">"update"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span>
          <span class="token property">"x"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"xscale"</span><span class="token punctuation">,</span> <span class="token property">"signal"</span><span class="token operator">:</span> <span class="token string">"tooltip.category"</span><span class="token punctuation">,</span> <span class="token property">"band"</span><span class="token operator">:</span> <span class="token number">0.5</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"y"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"scale"</span><span class="token operator">:</span> <span class="token string">"yscale"</span><span class="token punctuation">,</span> <span class="token property">"signal"</span><span class="token operator">:</span> <span class="token string">"tooltip.amount"</span><span class="token punctuation">,</span> <span class="token property">"offset"</span><span class="token operator">:</span> <span class="token number">-2</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"text"</span><span class="token operator">:</span> <span class="token punctuation">&#123;</span><span class="token property">"signal"</span><span class="token operator">:</span> <span class="token string">"tooltip.amount"</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
          <span class="token property">"fillOpacity"</span><span class="token operator">:</span> <span class="token punctuation">[</span>
            <span class="token punctuation">&#123;</span><span class="token property">"test"</span><span class="token operator">:</span> <span class="token string">"datum === tooltip"</span><span class="token punctuation">,</span> <span class="token property">"value"</span><span class="token operator">:</span> <span class="token number">0</span><span class="token punctuation">&#125;</span><span class="token punctuation">,</span>
            <span class="token punctuation">&#123;</span><span class="token property">"value"</span><span class="token operator">:</span> <span class="token number">1</span><span class="token punctuation">&#125;</span>
          <span class="token punctuation">]</span>
        <span class="token punctuation">&#125;</span>
      <span class="token punctuation">&#125;</span>
    <span class="token punctuation">&#125;</span>
  <span class="token punctuation">]</span>
<span class="token punctuation">&#125;</span>
</code></pre></li>
<li><p>G2可视化引擎</p>
<p>也是一种图形语法</p></li>
<li><p>EChart: 使用JS实现的JSON图形语法</p></li>
</ul>

    </div>

    
    
    
      


    <footer class="post-footer">
          <div class="reward-container">
  <div></div>
  <button>
    赞赏
  </button>
  <div class="post-reward">
      <div>
        <img src="/images/wechatpay.png" alt="Liu Kairui 微信">
        <span>微信</span>
      </div>
      <div>
        <img src="/images/alipay.png" alt="Liu Kairui 支付宝">
        <span>支付宝</span>
      </div>

  </div>
</div>

          

<div class="post-copyright">
<ul>
  <li class="post-copyright-author">
      <strong>本文作者： </strong>Liu Kairui
  </li>
  <li class="post-copyright-link">
      <strong>本文链接：</strong>
      <a href="http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/" title="2022寒假字节跳动前端训练营笔记">http://liukairui.me/article/2022寒假字节跳动前端训练营笔记/</a>
  </li>
  <li class="post-copyright-license">
    <strong>版权声明： </strong>本博客所有文章除特别声明外，均采用 <a href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.zh" rel="noopener" target="_blank"><i class="fab fa-fw fa-creative-commons"></i>BY-NC-SA</a> 许可协议。转载请注明出处！
  </li>
</ul>
</div>

          <div class="post-tags">
              <a href="/tags/%E5%89%8D%E7%AB%AF/" rel="tag"><i class="fa fa-tag"></i> 前端</a>
              <a href="/tags/%E7%AC%94%E8%AE%B0/" rel="tag"><i class="fa fa-tag"></i> 笔记</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/article/2022%E5%AF%92%E5%81%87%E7%99%BE%E5%BA%A6%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/" rel="prev" title="2022寒假百度前端训练营笔记">
                  <i class="fa fa-chevron-left"></i> 2022寒假百度前端训练营笔记
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/article/2022%E5%AE%9E%E4%B9%A0%E5%88%B7%E9%A2%98/" rel="next" title="2022实习刷题🔒">
                  2022实习刷题🔒 <i class="fa fa-chevron-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






    <div class="comments" id="valine-comments"></div>
</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">


<div class="copyright">
  &copy; 2019 – 
  <span itemprop="copyrightYear">2022</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Liu Kairui</span>
</div>
<div class="busuanzi-count">
    <span class="post-meta-item" id="busuanzi_container_site_uv">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="总访客量">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-item" id="busuanzi_container_site_pv">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="总访问量">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>
  <div class="powered-by">由 <a href="https://hexo.io/" rel="noopener" target="_blank">Hexo</a> & <a href="https://theme-next.js.org/muse/" rel="noopener" target="_blank">NexT.Muse</a> 强力驱动
  </div>
  <div class="addthis_inline_share_toolbox">
    <script src="//s7.addthis.com/js/300/addthis_widget.js#pubid=ra-6231eb6f709fc868" async="async"></script>
  </div><script
  async
  src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"
></script>

 
<script src="https://cdn.jsdelivr.net/npm/moment@2.22.2/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/moment-precise-range-plugin@1.3.0/moment-precise-range.min.js"></script>
<script>
  function timer() {
    var ages = moment.preciseDiff(moment(),moment(20201101,"YYYYMMDD"));
    ages = ages.replace(/years?/, "年");
    ages = ages.replace(/months?/, "月");
    ages = ages.replace(/days?/, "天");
    ages = ages.replace(/hours?/, "小时");
    ages = ages.replace(/minutes?/, "分");
    ages = ages.replace(/seconds?/, "秒");
    ages = ages.replace(/\d+/g, '<span class="daysCnt" style="color:#1890ff">$&</span>');
    div.innerHTML = `我已在此等候你 ${ages}`;
    div.className="workDays";
  }
  var div = document.createElement("div");
  //插入到copyright之后
  var copyright = document.querySelector(".copyright");
  document.querySelector(".footer-inner").insertBefore(div, copyright.nextSibling);
  timer();
  setInterval("timer()",1000)
</script>



    </div>
  </footer>

  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/@next-theme/pjax@0.5.0/pjax.min.js" integrity="sha256-3NkoLDrmHLTYj7csHIZSr0MHAFTXth7Ua/DDt4MRUAg=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js" integrity="sha256-yt2kYMy0w8AbtF89WXb2P1rfjcP/HTHLT7097U8Y5b8=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pangu/4.0.7/pangu.min.js"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/schemes/muse.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  
<script src="https://cdn.jsdelivr.net/npm/hexo-generator-searchdb@1.4.0/dist/search.js" integrity="sha256-vXZMYLEqsROAXkEw93GGIvaB2ab+QW6w3+1ahD9nXXA=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>


  <script class="next-config" data-name="mermaid" type="application/json">{"enable":true,"theme":"forest","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mermaid/8.14.0/mermaid.min.js","integrity":"sha256-7wT34TI0pEBeEFoi4z+vhuSddGh6vUTMWdqJ2SDe2jg="}}</script>
  <script src="/js/third-party/tags/mermaid.js"></script>

  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>

  
  <script data-pjax async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>


  <script class="next-config" data-name="leancloud_visitors" type="application/json">{"enable":true,"app_id":"ABKlVtS4cyaWYEwunPyK3sXt-9Nh9j0Va","app_key":"xxGXdTTEGEVifs2TLB35844I","server_url":"https://abklvts4.lc-cn-e1-shared.com","security":false}</script>
  <script src="/js/third-party/statistics/lean-analytics.js"></script>


  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","mhchem":true,"js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.0/es5/tex-mml-chtml.min.js"}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


  <script src="https://cdnjs.cloudflare.com/ajax/libs/quicklink/2.2.0/quicklink.umd.js" integrity="sha256-4kQf9z5ntdQrzsBC3YSHnEz02Z9C1UeW/E9OgnvlzSY=" crossorigin="anonymous"></script>
  <script class="next-config" data-name="quicklink" type="application/json">{"enable":true,"home":false,"archive":false,"delay":true,"timeout":3000,"priority":true,"url":"http://liukairui.me/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/"}</script>
  <script src="/js/third-party/quicklink.js"></script>
<script src="https://cdn.jsdelivr.net/npm/darkmode-js@1.5.7/lib/darkmode-js.min.js"></script>

<script>
var options = {
  bottom: '64px',
  right: 'unset',
  left: '32px',
  time: '0.5s',
  mixColor: 'transparent',
  backgroundColor: 'transparent',
  buttonColorDark: '#100f2c',
  buttonColorLight: '#fff',
  saveInCookies: true,
  label: '🌓',
  autoMatchOsTheme: true
}
const darkmode = new Darkmode(options);
window.darkmode = darkmode;
darkmode.showWidget();
</script>


<script class="next-config" data-name="valine" type="application/json">{"enable":true,"appId":"ABKlVtS4cyaWYEwunPyK3sXt-9Nh9j0Va","appKey":"xxGXdTTEGEVifs2TLB35844I","serverURLs":"https://abklvts4.lc-cn-e1-shared.com","placeholder":"请开始你的表演","avatar":"identicon","meta":["nick","mail","link"],"pageSize":10,"lang":"zh-CN","visitor":false,"comment_count":true,"recordIP":true,"enableQQ":true,"requiredFields":[],"el":"#valine-comments","path":"/article/2022%E5%AF%92%E5%81%87%E5%AD%97%E8%8A%82%E8%B7%B3%E5%8A%A8%E5%89%8D%E7%AB%AF%E8%AE%AD%E7%BB%83%E8%90%A5%E7%AC%94%E8%AE%B0/"}</script>
<script>
document.addEventListener('page:loaded', () => {
  NexT.utils.loadComments(CONFIG.valine.el)
    .then(() => NexT.utils.getScript(
      'https://cdn.jsdelivr.net/npm/valine@1.4.14/dist/Valine.min.js',
      { condition: window.Valine }
    ))
    .then(() => {
      new Valine(CONFIG.valine);
    });
});
</script>


  <script async src="/js/fireworks.js"></script>




  <script src="/js/activate-power-mode.min.js"></script>
  <script>
    POWERMODE.colorful = true;
    POWERMODE.shake = false;
    document.body.addEventListener('input', POWERMODE);
  </script>




  <script src="/js/wobblewindow.js"></script>
  <script>
    //只在桌面版网页启用特效 记得同步到header.njk
    if( window.innerWidth > 768  ){
      $(document).ready(function () {
        
          $('body>main>header').wobbleWindow({
            radius: 50,
            movementTop: false,
            movementLeft: false,
            movementRight: false,
            debug: false,
          });
        

        //
        //  $('body header>aside').wobbleWindow({
        //    radius: 50,
        //    movementLeft: false,
        //    movementTop: false,
        //    movementBottom: false,
        //    position: 'fixed',
        //    debug: false,
        //  });
        //

        
          $('body>footer').wobbleWindow({
            radius: 50,
            movementBottom: false,
            movementLeft: false,
            movementRight: false,
            debug: false,
          });
        
      });
    }
  </script>


 
<script>
  $(document).ready(function(){
    var beian = document.querySelector(".footer-inner > .beian > a");
    var cpr=document.querySelector(".footer-inner > .copyright");
    var cnz=document.querySelector(".workDays");//.parentNode;
    var bsz=document.querySelector(".busuanzi-count");
    if(cnz!=null&&bsz!=null)
      cnz.parentNode.insertBefore(bsz,cnz);
    if(bsz == null || bsz == undefined || document.querySelector("#busuanzi_value_site_pv").innerText=="" || document.querySelector("#busuanzi_value_site_uv").innerText == "")
      bsz.remove();
    checkIndex();
    if(beian){cpr.classList.add('split-line');cpr.appendChild(beian);}
  })
  $(document).on('pjax:complete',checkIndex);
</script>



<script src="/live2dw/lib/L2Dwidget.min.js?094cbace49a39548bed64abff5988b05"></script><script>L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"log":false,"model":{"jsonPath":"/live2dw/assets/hijiki.model.json"},"display":{"position":"right","width":150,"height":300},"mobile":{"show":false},"react":{"opacity":0.7}});</script></body>
</html>
